The Pragmatic Programmer: 20th Anniversary Edition, 2nd Edition: Your Journey to Mastery
David Thomas, Andrew Hunt, et al.
4.8 on Amazon
396 HN comments
Masters of Doom: How Two Guys Created an Empire and Transformed Pop Culture
David Kushner, Wil Wheaton, et al.
4.8 on Amazon
262 HN comments
Designing Data-Intensive Applications: The Big Ideas Behind Reliable, Scalable, and Maintainable Systems
Martin Kleppmann
4.8 on Amazon
241 HN comments
Clean Code: A Handbook of Agile Software Craftsmanship
Robert C. Martin
4.7 on Amazon
232 HN comments
Code: The Hidden Language of Computer Hardware and Software
Charles Petzold
4.6 on Amazon
186 HN comments
Cracking the Coding Interview: 189 Programming Questions and Solutions
Gayle Laakmann McDowell
4.7 on Amazon
180 HN comments
The Soul of A New Machine
Tracy Kidder
4.6 on Amazon
177 HN comments
Refactoring: Improving the Design of Existing Code (2nd Edition) (Addison-Wesley Signature Series (Fowler))
Martin Fowler
4.7 on Amazon
116 HN comments
Thinking in Systems: A Primer
Donella H. Meadows and Diana Wright
4.6 on Amazon
104 HN comments
Superintelligence: Paths, Dangers, Strategies
Nick Bostrom, Napoleon Ryan, et al.
4.4 on Amazon
90 HN comments
The Idea Factory: Bell Labs and the Great Age of American Innovation
Jon Gertner
4.6 on Amazon
85 HN comments
Effective Java
Joshua Bloch
4.8 on Amazon
84 HN comments
Domain-Driven Design: Tackling Complexity in the Heart of Software
Eric Evans
4.6 on Amazon
83 HN comments
Weapons of Math Destruction: How Big Data Increases Inequality and Threatens Democracy
Cathy O'Neil
4.5 on Amazon
75 HN comments
A Philosophy of Software Design
John Ousterhout
4.4 on Amazon
74 HN comments
noir_lordonJan 9, 2019
http://lucacardelli.name/Papers/TypefulProg.pdf is now next on my list when I finish reading A Philosophy of Software Design (which is brilliant if you haven't seen it).
afarrellonSep 6, 2019
A Philosophy of Software Design by John Osterhout is a good book on these questions.
vitornovictoronNov 9, 2018
tejinderssonAug 17, 2018
grammarnazzzionMay 25, 2021
dvirskyonDec 23, 2018
https://www.goodreads.com/book/show/39996759-a-philosophy-of...
augustkonDec 22, 2020
pbadenskionDec 8, 2020
devnonymousonJuly 24, 2021
[1] https://hn.algolia.com/?q=a+philosophy+of+software+design
hodgesrmonSep 4, 2018
auslegungonOct 1, 2018
bobwaycottonDec 26, 2018
a_bonoboonFeb 3, 2020
signa11onApr 24, 2020
afarrellonApr 13, 2020
Concise, readable, and highly applicable.
afarrellonMay 30, 2020
Very well-written. At 190 pages, quite likely finish-able in a weekend. But if you get 70% of the way through it, that is still very valuable. It makes sense as an underlying set of principles that explain why you would use design patterns.
noir_lordonJuly 29, 2019
tmalyonSep 16, 2018
For technical skills, I recommend reading Clean Code, Test Driven Development, and The Philosophy of Software Design.
brian_spieringonMay 29, 2019
timClicksonJuly 5, 2019
girishsoonApr 16, 2021
atmosxonFeb 7, 2019
So without context is hard to tell, but it’s a quick read, you might want to take a look and spot possible improvements without sacrificing quality.
tincholioonOct 23, 2020
That book is a little gem, short and well-written
afarrellonJuly 16, 2020
MeteorMarconNov 10, 2019
https://www.amazon.com/t/dp/1732102201
It argues, among other things, that deep interfaces matter more than code complexity inside a module.
yumaikasonOct 3, 2018
It'll give you a lot of higher level things to think about as you're diving deep into your first tech stack.
afarrellonMay 9, 2020
It is concise and presents a clear view of what makes code easier to work with. I've found its concepts useful when trying to think of what to say during code reviews.
augustkonMar 25, 2020
I couldn't disagree more, the grown up programmers use a strategic approach, not a tactical one. As Jonh Ousterhout put it in his book A Philosophy of Software Design "The first step towards becoming a good software designer is to realize that working code isn't enough."
auslegungonDec 2, 2018
2. A Philosophy of Software Design https://www.amazon.com/dp/1732102201/ref=cm_sw_r_cp_api_i_EK...
3. Haskell from First Principles http://haskellbook.com
4. Les Miserables
5. Continuous Delivery https://continuousdelivery.com
abhghonOct 28, 2019
noir_lordonAug 9, 2020
I don't mind high level videos to give a 10,000ft view but for everything else the written word wins every time.
Currently re-reading A Philosophy of Software Design and just started "Grokking Algorithms" alongside the 2-3 fictional books I have on the go at any given time.
dmuxonJan 25, 2020
There is a great section of John Ousterhout's "A Philosophy of Software Design" that goes into this. He mentions that moving code to functions / methods doesn't eliminate complexity, it nuat kind of shifts it: it adds complexity to the "interface" of the module.
Sometimes leaving code inline with its original context is better.
lboassoonAug 30, 2018
[0] https://www.amazon.com/Philosophy-Software-Design-John-Ouste...
discreteeventonNov 13, 2020
noir_lordonJune 26, 2021
In "A Philosophy of Software Design" Ousterhout talks about the difference between tactical and strategic programming (great book mostly because it codifies a lot of what I think is the "One True Way" so I'm biased) and it's really easy to bang out a fix for variant 98 of the bug vs rethinking it so variants 0 through 97 which haven't been reported yet but exist can't happen.
hodgesrmonJune 13, 2018
timclarkonSep 5, 2020
This has an interesting generic discussion of API design which is technology agnostic.
noir_lordonFeb 22, 2019
It's a shortish book but there is stuff in it I'm still unpacking on the third read through and a lot of stuff I sorta instinctively knew but it's nice to see someone else thinks the same.
gregfjohnsononMay 12, 2021
John Osterhout wrote what may be the best elaboration of this perspective in his wonderful book "A Philosophy of Software Design."
A couple of related thoughts from an old grizzled programmer (moi ;-), gregfjohnson.com):
Rule number one: All code must follow the Porthole Principle. The fundamental issue in programming is that we each look out at the world through a mental "porthole" that limits our field of view. We are limited in how much we can see and understand at any one time. Therefore, systems must be structured so that they can be understood completely, at all levels, even though we are only allowed to investigate them piecemeal, through our own limited and finite cognitive windows.
Abstraction is the essential tool that allows us to create systems of arbitrary size and complexity. A beautifully designed abstraction is easy to understand and use. It is so trustworthy that you don't feel any need to worry about how it is implemented. Finally, and most importantly, it enables you to reason with rigor and precision about the correctness of the code you are writing that makes use of it.
lstamouronMay 12, 2021
If you like this post, you might also like reading the relatively short book, A Philosophy of Software Design by John Ousterhout, or the talk you'll find on YouTube by the same name, which covers roughly half the topics in the book.
hikarudoonJuly 6, 2020
"... the greatest limitation in writing software is our ability to understand the systems we are creating."
"Complexity manifests itself in three general ways... change amplification, cognitive load, and unknown unknowns."
"Complexity is caused by two things: dependencies and obscurity."
"Obscurity occurs when important information is not obvious."
"The goal of modular design is to minimize the dependencies between modules."
tmalyonDec 12, 2018
Extreme Ownership - I also really enjoyed this book. I listened to the audio and it was read by the authors. Both Navy Seals, the stories they used about their time in war was very eye opening. The concepts are all about leadership, and if you a manager or part of a team, you will get some benefit.
Getting Things Done - 2001 edition, very practical approach to organizing everything on your plate. I will probably re-read this again.
Learning How to Learn: How to Succeed in School Without Spending All Your Time Studying; A Guide for Kids and Teens - a great book that has great tips on learning for kids and adults.
A Philosophy of Software Design - still reading it, I really am enjoying it so far. I like the big picture approach it takes to discussing software design and complexity.
Mindset - I just started this book. So far it is just explaining the general concept in different ways. I am hoping the latter part will get into some practical tips and methods.
blubonAug 25, 2019
"Enterprise architecture" was not relevant for me, I wasn't doing any EA when I started reading it and quickly lost interest. The only potentially engaging topic was concurrency, but there are much better books available about that topic.
"Pattern-Oriented Software Architecture" (I am only familiar with vol 1 & 2) has wider applicability and is more compelling in my opinion. And they have references and examples. For instance the Pipes & Filters architecture patterns gives UNIX [Bac86], CMS Pipelines [HRV95] and LASSPTools [Set95] as examples and references "The Pipeline Design Pattern" [VBT95].
I do see case studies and references, but not from these authors I mentioned.
lstamouronSep 21, 2019
Also relevant, the Design Structure Matrix (DSM): https://dsmweb.org/ and https://mitpress.mit.edu/books/design-structure-matrix-metho... (mostly learning by example, not all software-relevant, available as an e-Textbook on Amazon) If you code in Java, IntelliJ has this diagram included.
Finally if you’re looking on advice on how to break software into modules based on making your API surfaces easier to use for yourself and other programmers, have a look at A Philosophy of Software Design. It’s not comprehensive, but it’s concise and relatively easy to read: https://books.google.ca/books/about/A_Philosophy_of_Software...
tmalyonMar 21, 2019
Clean Coder by Bob Martin - good ideas on being a professional programmer
A Philosophy of Software Design by John Ousterhout - big picture ideas on design
Test Driven Development by Kent Beck - good basis for thinking about design and testing
Legacy Code by Michael Feathers - understanding the issues of legacy code helps us to design better software
layer8onDec 8, 2020
What books do you recommend though to get novice (or not so novice) programmers up to speed? IMO there is a lack of modern literature and general introductory material to the kind of wisdom you otherwise only get after decade(s) of software development (if at all, for quite a number of people).
A recent one I liked is “A Philosophy of Software Design”, but it only covers so much ground, and some of its advice requires further qualification.
JtsummersonMay 25, 2021
dgb23onAug 9, 2021
Code doesn't magically become less complex by hacking it into pieces.
philosopher1234onMar 13, 2020
Also, your point about the meaning beyond the code can be served by a comment, which drops the constraint of "don't make it too long" and "write in camel case", and also allows inline code reading!
There's a time and a place for everything. I reccomend "A Philosophy of Software Design" for a book that elaborates on the idea of "less and longer methods tend to be better than many concise methods".
What you want to make short/simple is the API, rather than the implementation!
blubonAug 24, 2019
The fact that they're the author of a well-known piece of software helps, although we should not use this as the main criteria to evaluate a text.
Offering at least evidence based on experimentation is essential if we want to move past personality cults and having entire teams work based on what someone wrote on a blog somewhere.
throwaway16011onSep 26, 2020
Thanks for the kind words!
> From your post it is a bit unclear what you mean by feeling under-experienced compared to your peers. Is it at technical level? Work ethic/principles? Understanding of the whole technology stack? Or perhaps process in your company?
I feel the greatest trepidation around devops. Particularly in recent years I have noticed I am struggling to grasp the fundamental concepts of common tools. Kubernetes is a convenient example. Beyond k8s itself, I feel as if I'm drowning in the ecosystem which has grown around it.
At some point my mind seems to all lost all plasticity.
> These should give you, in my humble opinion, some fresh motivation and abstract overview on software development in general.
Absolutely! Both books gave me great encouragement very early in my career, I should read them again. Indeed, I will hopefully have a greater appreciation and better understanding of the topics covered now that I have more experience.
I stopped reading books on software around the time I started feeling inadequate in my position. They became more of a source of anxiety than inspiration. That must sound perverse!
I recently started reading "A Philosophy of Software Design" (978-1732102200). It has been a refreshing experience and I am hoping eases my back into such literature.
notoriousarunonFeb 18, 2021
These books will help you day-to-day with your general programming knowledge...
> Philosophy of Software Design https://www.amazon.com/Philosophy-Software-Design-John-Ouste...
> The Pragmatic Programmer https://www.amazon.com/Pragmatic-Programmer-Journeyman-Maste...
> Clean Code https://www.amazon.com/Clean-Code-Handbook-Software-Craftsma...
> Mythical Man-Month https://www.amazon.com/Mythical-Man-Month-Anniversary-Softwa...
jasimonOct 30, 2018
One oddity is the view of the class as the only real scope at which one can build abstractions. The idea that one can use little abstractions to build big abstractions, without cluttering the final abstraction to be presented to the user, is nowhere in sight.
Most shockingly to me, I've found no reference to types as a design tool. Sure, precise names help you avoid confusing physical block ids and logical ones. But wouldn't a type-based distinction be way better?
- https://twitter.com/yminsky/status/1005066579929911296
JtsummersonApr 16, 2021
A Philosophy of Software Design by John Ousterhout, short book, quick read. I'll be rereading it once I figure out which bookshelf my wife hid it on (she doesn't like my bookstack approach to "organizing" and moved many things to shelves while I wasn't paying attention).
bwh2onApr 16, 2021
In those last 70 pages, the author advocates strongly for lengthy comments which felt excessive and often unnecessary to me. Here's an example from page 124:
AlexCoventryonSep 9, 2018
Try The Art of Readable Code (a pair of google authors, IIRC), and Ousterhout's A Philosophy of Software Design.
sureshjayaramanonMar 22, 2019
pvarangotonDec 16, 2018
It's also not too different to what old books like Fowler's refactoring or the Working With Legacy Code book say, or what modern books like Philosophy of Software Design say.
afarrellonJuly 9, 2019
fdsvnsmvasonSep 10, 2018
Robert C. Martin, Clean code: https://www.amazon.com/Clean-Code-Handbook-Software-Craftsma...
Vaughn Vernon, various: https://vaughnvernon.co/?page_id=168
Steve McConnell, Code Complete: https://www.amazon.com/Code-Complete-Practical-Handbook-Cons... 2
Clean coder: https://cleancoders.com/ videos
Hunt and Thomas, The Pragmatic Programmer: https://www.amazon.com/Pragmatic-Programmer-Journeyman-Maste...
Hitchhiker's Guide to Python: https://docs.python-guide.org/
Dustin Boswell The Art of Readable Code: https://www.amazon.com/Art-Readable-Code-Practical-Technique...
John Ousterhout, A Philosophy of Software Design: https://www.amazon.com/Philosophy-Software-Design-John-Ouste... This one looks particularly interesting, thanks AlexCoventry!
Kent Beck, Test Driven Development: https://www.amazon.com/Test-Driven-Development-Kent-Beck/dp/...
Dan Bader, Python Tricks: The Book: https://dbader.org/
Ian Sommerville, Software Engineering: https://www.amazon.com/Software-Engineering-10th-Ian-Sommerv...
Svilen Dobrev, various: http://www.svilendobrev.com/rabota/
dgb23onJuly 19, 2021
- Coders at Work (Seibel)
- Working in Public (Eghbal)
The first one is very entertaining. Read it a couple years ago and found it gives some valuable perspective. The second one is on my reading list, it was recommended around these boards.
Related to software design, there are many. The two that are on my recent list are:
- Software Design for Flexibility (Sussman, Hanson)
- A Philosophy of Software Design (Ousterhout)
I can't comment personally on their content yet, still have to work through those two, but I have zero doubts to learn something valuable. Certainly consider them.
devchris10onJuly 22, 2020
cliffcroslandonAug 24, 2019
I appreciate that Ousterhout tries to support these principles with some data from his own experience (building Tcl, RamCloud where Raft consensus was discovered, etc) and from code reviews of student projects in his design course, but he admits that there is a lack of data about things like design.
Sample principles from Ousterhout:
* When developing an interface, favor exposing a small number of functions each with deep functionality over exposing a large number of functions each with shallow functionality. For example, favor Unix file I/O interface (open, close, read, write, unlink) over Java file I/O interface (File, FileReader, BufferedReader, FileWriter, BufferedWriter, FileNotFoundException, ... etc.)
* When choosing between keeping your code specific and keeping your code general, favor "somewhat" general. For example, instead of exposing "deleteNextCharacter(text, pos), deleteNextWord(text, pos), deleteNextSentence(text, pos)", just expose "delete(text, pos, length)" and let the caller use it how they will.
svatonJan 27, 2019
• https://news.ycombinator.com/item?id=18959636 (John Carmack on Inlined Code (2014))
• This comment, which contains a useful example: https://news.ycombinator.com/item?id=18832382
Please let me know of any further discussion on the topic. (I'm also reminded of Ousterhout's advice in A Philosophy of Software Design that “classes should be ‘thick’” — see talk https://www.youtube.com/watch?v=bmSAYlu0NcY or (unrelated) slides: https://platformlab.stanford.edu/Seminar%20Talks/retreat-201... )
One thing I see people miss in this discussion is that there's a tradeoff between having an individual function be understandable (shorter functions are easier to understand) having the entire codebase or interrelationships between functions be easier to understand (fewer functions are easier to understand). When there's an example presented like in the post, it's often presented as an example with a single function, and of course four short functions may each be easier to understand than a single function, but you've also added three nodes to the “graph” (of functions and calls between them) and now you need to study whether these functions are called from anywhere. To make up for this one may start introducing classes/objects to indicate “private”/“public” functions, and so on. (Some languages allow nested functions, which can help.)
Most of all I'd say reading very different styles of code, and seeing how people achieve great things in unusual ways (e.g. with lots of abstraction, or with very little abstraction), can be an illuminating experience (see my comment in this thread about reading Knuth's programs).
hodgesrmonAug 15, 2018
Even with that structure I found it challenging to develop a good reviewing style that picked up the important stuff without getting bogged down in silly details that lead to arguments. Reading John Ousterhout's "A Philosophy of Software Design" was really helpful. He focuses on module decomposition, quality of public interfaces, and documentation among other things.
achouonJune 21, 2019
This applies to the microservice/monolith debate as well. And it basically boils down to the observation that having lots of shallow services doesn't really reduce complexity. Each service may be simple unto itself, but the proliferation of many such services creates complexity at the next level of abstraction. Having well designed services with a simple API, but hide large amounts of complexity beneath, really reduces cognitive load for the system as a whole. And by "simple API" I think it's important to realize that this includes capturing as much of the complexity of error handling and exceptional cases as much as possible, so the user of the services has less to worry about when calling it.
[1]: https://www.amazon.com/Philosophy-Software-Design-John-Ouste...
afarrellonApr 6, 2020
As a field, we would benefit greatly from learning more cognitive science.
A core suggestion of John Osterhout's book A Philosophy of Software Design is to have well-named modules with 'thin' interfaces which accomplish a reasonably-deep set of responsibilities. But...why?
Working Memory -- Humans have limited Working Memory.
If you give a function:
- A clear name.
- Few simple parameters.
- No side-effects not in the name.
- No GOTOs or exceptions.
then a human can glance at it, put the name and parameters into working memory, and carry on.
But if you split up a namable responsibility across multiple files, then a human reading the codebase to understand data flow would need many more open editor windows or to hold much more info in working memory.
elliusonFeb 22, 2020
Complexity comes from two sources in software projects. The first is the domain. As other commenters have pointed out, domain experts are usually half-aware of their domain requirements because much of the complexity has been buried under their expertise and intuition. Domain requirements also inherently change over time as markets, professional standards, and technology evolve. So the process of development involves a shifting discovery of new aspects of the domain as things which were unconscious become consciously learned.
The other aspect of complexity is the technology applied to the problem. Computer technology is inherently complex, and the imperfect mapping between domain problems and technology adds a third angle.
The best books I've seen for dealing with these problems are "Clean Architecture," "A Philosophy of Software Design," and "Principles of Product Development Flow." The first two explain how to build good systems that encapsulate complexity and are geared towards changeability. Such systems are flexible as new aspects of domain complexity are discovered over time. The latter book takes a higher level view of how to design projects to cope with the discovery process in a way that is economically viable and justifiable to the people financing projects, and also in a way that arranges work so that developers can actually be productive and not become swamped by the complexity problem or bad processes and practices.
layer8onDec 18, 2020
Of course, the answer to that question can change over time, and one has to combine or duplicate accordingly. This also serves to document the intent that “yes, these two occurrences are expected to evolve identically”, or “no, these two occurrences are expected to evolve independently, even though they currently happen to look the same”.
The article is correct though that there is a trade-off in terms of the complexity created by the abstraction, and in how important the “common truth” is. Sometimes a source comment pointing out the dependency is better than introducing a nontrivial abstraction.
The book “A Philosophy of Software Design” argues that there are two sources of complexity in software: dependencies and obscurity. Combining two similar pieces of logic into one can reduce dependencies (of one having to be changed when the other is changed), but can increase obscurity due to the added abstraction. If the combining was done for the wrong reasons (the two occurrences actually need to evolve independently), then the dependencies are increased instead of reduced.
bertmuthalalyonMay 1, 2020
Otherwise this essay is spot on when it comes to essential conplexity.
Incidentally, the question of “where complexity lives” is one of the focal points of “A Philosophy of Software Design,” which comes highly recommended if you’re trying to come up with your strategy for managing complexity from first principles.
bchonJuly 29, 2019
TeMPOraLonDec 28, 2018
In Philosophy of Software Design, J. Ousterhout says that this TDD practice encourages "tactical programming", i.e. trying to solve the current open ticket with minimum amount of work, instead of solving the problem correctly. Personally I'd go further. To me, this approach encourages replacing your brain with a dumb gradient descent process. Instead of thinking about the problem and solution, you just keep writing an ever larger monster whose sole purpose is to interpolate between test cases.
Tests themselves are useful. Following a process that makes meaning implicit instead of explicit? Not so much.
praptakonApr 12, 2021
The width is defined as the size of the interface (the cost) and the depth as the functionality that it buys you or maybe the complexity it hides (I'm recalling from memory, don't have the book at hand).
A file system that exposes the file interface (as in Unix) is given as a positive example. It has few functions and buys you, well, everything a file system offers.
shidoshionAug 31, 2018