Ask HN: Suggested software /design/ books?
I've learnt plenty of programming languages, from C to Java to Squeak to Haskell to Lisp, but I have not made as many 'finished' programs as I'd like.
I've found, despite knowing and using plenty of programming constructs, I've not really managed complexity as well as I'd like.
The result being my programs end up being too complex to maintain, with the ultimate result being they're left to rot in some directory in my filesystem.
I've heard of 'Thinking in Java/C++' and 'The Practice of Programming'. Does HN have any recommended books on software design?
19 comments
[ 2.9 ms ] story [ 24.1 ms ] threadThat said it doesn't mean you can't learn this skill! I think the best place to start is finishing a decently sized program. The first time I did this I was extremely unhappy with my design. However, each time it got easier and my designs started getting better.
Second, start reading some large code bases. These are often difficult to read, but they can teach some tricks and some methodology. This summer I read Tomcats source code with the aid of "How Tomcat Works: A Guide to Developing Your Own Java Servlet Container."[1] While not enjoyable (it was for my job), the experience was worth doing.
In the end, all programmers constantly struggle to make scalable, reusable, and maintainable systems. Few programmers achieve a soundly designed system but we can certainly strive to achieve perfection in our designs.
[1] by Budi Kurniawan; Paul Deck, ISBN: 978-0-9752128-0-6
* Design Patterns: Elements of Reusable Object-Oriented Software
* Refactoring: Improving the Design of Existing Code
* Clean Code: A Handbook of Agile Software Craftsmanship
* Code Complete: A Practical Handbook of Software Construction
And some others:
* Working Effectively with Legacy Code
* Domain-Driven Design: Tackling Complexity in the Heart of Software
I'm not a fan of this book. I've been in too many shops where it's become gospel and the code becomes an unnavigable swamp of singletons and factory classes and who-knows-what.
http://www.theserverside.com/tip/Evil-Design-Patterns-When-D...
If you need your code to construct objects without knowing the type, then you need a factory (or other creation pattern). If you don't -- it's overkill. They are using a solution to a problem they don't have.
You feel your code is clunky because of lack of design. And lack of design comes from the fact that we usually don't know what we want to design till we design it. This is where prototypes come in handy because prototypes shed the light on problems that we didn't foresee. Rule of thumb for prototype code is to throw it away once you are done.
What I am trying to say here is that you don't need a book to learn what you are asking for, you need experience.
Find an open source project on the web that has the kind of complexity you want and start digging through the code. Better yet, start fixing bugs. It'll force you to wrap your head about how they did things. With enough of that, you'll even figure out why they did it, and that's as much as anyone else can teach you.
I find myself taking the first solution that appears to me, which is not great. I'm trying to adopt more of a sketching approach, writing a few bits of code to see how things would interact, and working out where the complexity would bite me in a design.
They have a lot of good authors who focus on different aspects of design and architecture.
I also enjoyed Implementation Patterns by Kent Beck. It is not so much on the architecture of the system, but focuses on the implementation of classes and routines.
* David Hanson: A Retargetable C Compiler
* John Lakos: Large-Scale C++ Software Design
* VA: Beautiful {Code, Data, Testing}
* Design pattern books maybe
* Code Complete
* Fred Brooks: The Mythical Man Month
* Fred Brooks: Design of Design
* "Best of" books like C++ Pearls or More C++ Pearls
* Michael Abrash: Grapics Programming Black Book
* Looking at John Carmack code, eg. in my github repo at http://github.com/mtrencseni
* In the old days they had trade magazines, which unfortunately gave way to blogs. If you're interested in C/C++, there was The C/C++ User's Journal, if you ask them they'll just send you a free DVD with all the issues, and there was the C++ Report
There are many aspects to maintaining a good project:
* knowing your tools; if you use Makefiles/svn/make/gcc/Visual Studio, buy a book on it, write some helper scripts, etc.
* knowing a comfortable subset of your language; pick 2 (at most 3) languages and be good at those, really good at one
* know the idioms of your language and framework(s)
* physical layout: putting code and resources into folders, files, including, naming, etc. in a consistent manner; eg. this is covered in Large Scale C++
* consistent naming and commenting: your code should be pleasant to look at in terms of naming, declarations, length of blocks, tabulation, etc., eg. look at John Carmack code
* DRY, KISS, etc.
* logical design, distributing code and functionality across your program: that's the tough one. Personally I don't find DPs to be generally useful; instead:
* constant refactoring: your motto wrt. refactoring must be "no fear", and you have to set aside time for this. eg. I spend weeks refactoring
* when writing a program, don't start hacking away to get something out the door, think it over, get to know your subject, flesh out its details (eg. read up on it, how have others solved it), so you can appreciate its beauties and difficulties, and if possible
* copy your predecessor's successful ideas and designs
* build yourself a nice 'lib' that you reuse and grow across your projects, but be careful not to turn it into a monster =)
* trick: you can distribute some of these among team members, eg. see the chapter on the Surgical Team in Mythical Man Month, which I subscribe to
All of that is a long-winded way of introducing the suggestion that you learn to program by programming. The second-best is understanding others' programs (select well-respected, progressively larger codebases). Books, suggestions of which I hope others will provide, may give you some good ideas and thought patterns. "Software design" is a vast field with tons of completely obsolete advice, and terrible amounts of overengineering. Perhaps something like an agile workflow book, "The Pragmatic Programmer" once you can construct programs.
You already know more programming paradigms than most working programmers including those that have contributed to software you use daily. That's great and invaluable. Each of these paradigms told you something new about managing complexity (message passing in Squeak, reflection in Java, metalinguistic abstraction in Lisp). You can now apply them outside of those languages (that's what Design Patterns are about): multiple dispatch via Visitor Pattern in Java, message passing OO in Lisp[1], interfaces and implementations in C and so on.
[1] http://okmij.org/ftp/Scheme/oop-in-fp.txt
What you don't have is practice applying these lessons iteratively: put in effort, ship something (even with inadvertent mistakes), receive constructive criticism, find bugs and missing features, put in effort to improve design as needed to add features and fix bugs, ship an improved version and so on.
You're afraid of shipping something you're embarrassed of, or of failing to ship something that delivers on its promises. Every programmer feels that, it's perfectly natural and fine: its what motivates us to improve. Acknowledge this fear, but don't let it paralyze you.
There's a Russian proverb: eyes fear, hands do. Apply it.
But before you do so, here are some of my suggestions, take it with a grain of salt because it may not work for you.
1) Quit HNews.
You won't learn how to build software here. Most people rehash the same "technical" speak again and again about consumer application (web scaling, javascript, functional, anti-enterprise, etc).
2) Clear your mind
Go out. Walk in the park more. Don't think too much about programming languages. I suspect you're drawn to a distortion field of "learning programming language X will make you better at Y". Once you got that cloud away, start exploring what you wanted to do.
3) Pick a language and be good with it
Again, don't worry too much about the other programming languages unless you want to learn them for the fun of it. If your goal is to build something, stick with one.
Perhaps the most educational thing you can do is to choose a real project and write the user level documentation for it, and the use cases, the APIs and the unit tests: all before you begin to code.
Get other people to read your documentation and comment. If anyone can identify elements that are not needed, remove them. Don't worry much about implementation or optimization at this stage, worry about clarity and elegance of design.