For reasons unknown to me, intro-level books for programming languages stopped including exercises. K&R had exercises, SICP had exercises, Dragon Book had exercises. Clojure in Action, Clojure programming, Joy of Clojure, Programming Erlang — none of those have any. What happened? Are they trying to conserve space?
Since you mention Joy of Clojure, it's worth a response.
First, I would love to include exercises, however two factors conspire(d) against us. First, some of our favorite C.S./programming books have amazing exercises, so we respect the art of creating interesting and relevant supplementary material. It is no small task to design a book that flows, teaches the right lessons and also provides a set of exercises.[1] If we were to include exercises we would think very hard about what to include and how it fits into the book as a whole.
Second, the schedule for our book was quite tight given that we both have families and full-time jobs. We could write the book in a satisfactory way on time, or we could include exercises. We chose to write the best book possible given our time and ability (or lack thereof). We actually did create some exercises, but felt it was not worth including a partial set. Maybe next time. However, all of the same considerations would apply.
As you'll notice, our exclusion had nothing to do with page count.
Great question.
[1]: I should say, "for us" since others seem to do it easily.
I don't see this as a rant. I think this is a genuine problem/complaint with recent programming books.
I am not sure what started the trend or why it continues. Exercises are where the learning happens for me. Perhaps well crafted exercises are more difficult to write than programming language documentation/cookbook style books? (which is what most of these books are)
There is less focus on books as a teaching method, and rather just a collection of manicured examples and well ordered documentation. (which are also valuable, but not a great way for me (and others, I suspect) to truly learn a language or technology)
While I haven't read the four you mention not having examples, in my experience, "conserving space" is the last thing most programming books do.
Reading this post, my first thought was "How do you read a programming book 3 times? They're so long?"
I actually feel like most programming-related books are artificially padded with unneeded content, just for the sake of making them longer. Perhaps so they'll seem more like they're worth their price?
In my opinion, too-long technical books are a problem. If you've only got an hour or two a day to read, it can take a week or two to get through a decent-sized technical book. Add in xentronium's point about lack of exercises, and I don't know how anyone is supposed to retain much knowledge from these books.
I understand that at least one publisher prefers thick books because that makes the spine wider and therefore the book is more visible on the shelf in the bookstore.
Maybe now that so many books are purchased online this isn't as much of a concern.
I couldn't care less about programming exercises, but I'd love to have some mini project ideas or examples at the end of every chapter so you can put in practice what you've just learn. I've found that I learn stuff better when I try to adapt code examples to some domain of my own, but sometimes you just lack the drive or are tired of working on the same set of personal "hello world" projects.
In this regard Practical Common Lisp is a killer book. Definitely one of my favorites. It's really a pity that there aren't many other books mimicking its style (recommendations are welcome).
> I couldn't care less about programming exercises, but I'd love to have some mini project ideas or examples at the end of every chapter so you can put in practice what you've just learn.
"mini project ideas or examples at the end of every chapter" sound like exercises to me?
Many SICP exercises would be similar to, "Ben Bitdiddle thinks he can define COND like this: [bunch of code]. Show why he's wrong." Which is not practical whatsoever--it's clearly a short problem for academic purposes.
In contrast, PCL would say, "Now we can write a media server, let's go!"
As someone who has semi-recently started getting back into programming, this is a big deal for me. Starting with Ruby (reading The Well Grounded Rubyist) -- I read the book, felt like I understood a lot of it well except some of the more advanced stuff, but was stumped when considering my own practice problems and how to solve them.
Providing small, challenging problems is a very valuable resource. I'm currently reading An Introduction to Programming in Java (as preparation for the Princeton Algorithms course on Coursera). While the book may not be the best Java book, each section has 40+ programming exercises. Sometimes the exercises are boring, but I do most of them anyway because they are in themselves a learning exercise.
Brian Marick's recent book FP for the OO Programmer (https://leanpub.com/fp-oo) has a phenomenal set of integrated exercises. I think they're valuable even for an experienced developer in thinking through problems in new ways.
I think writing great exercises that teach and integrate with the text is really hard and many authors/publishers don't have the time or incentive to do so.
First of all, there are a few main categories of exercises I encounter when I read:
1. exercises left to the reader
2. exercises with solutions
When I read a book, I typically dislike exercises left to the reader, especially because when I get to work on a solution, I have no idea whether it's any good at all, especially in a language-specific book where there's a good chance my solution is bad for not being familiar with the language -- not necessarily a lack of reasoning as much as familiarity.
SICP is one exception to this in my experience (I haven't read all the books in your list), because it's not language specific, and I'm reading it with the known mindset it will take months to go through. I'm not reading it to learn Scheme, but to learn to program, and in my opinion, there's a different mindset involved. Still, there were times where I wished I could get solutions without buying a separate manual. I ended up looking for solutions online and found many of them; this isn't an option with many new books, and shouldn't be expected as a feature.
For exercises with solutions, I like these a lot better to begin with. I can work on things until I fail, absorb the solution by reading it, and gaining experience. If you have plenty of exercises, the solutions will significantly increase the volume of the book, though. An online repository is a very decent solution, and even lets you add comments and explanations.
I want to focus on the idea of explanations. Exercises with flat solutions without any explanation of what is going on, just "it works" are something that somewhat annoys me. "Here's code, figure it out kiddo" is a valid approach and makes sure the reader that goes through it still understands a lot, but it doesn't mean the reader won't miss stuff.
If I take the typical quicksort example of functional languages and just say "Implement quicksort using language X" and show one solution, it's up to the reader to figure out whether it's optimal, demonstrative, etc. ("Why is it important to pick a pivot the way it was done?") If there are indications, then it's nice to know how the code works, but you don't always get to understand how to create such code on your own. You will tend to know why the code is the way it is, but not necessarily how to build similar though different code on your own -- there's a subtle distinction there.
This is where a lot of exercises fall short, in my opinion. It's more obvious in math books where only the final answer is given. You can validate your answer, but if you don't know how to come up with one, you're lost. Good luck, ask someone or go back until you're brilliant enough to do this exercise. If there are steps done, nothing tells the reader why that one was picked or why the author decided to attack from that angle instead of any other one. Personally, this would tend to get me into the area where I know how to solve the exercises in the book, but I'm quite unsure about how to solve those outside of it.
I do prefer the approach where the exercises are something you can be guided through. The author explains the design decisions and why things are the way they are. I found it's a format that made more sense to me when I was watching screencasts, or when working with a trainer (or as a trainer), teacher, or whatever. It's how I was taught sports, music, and so on. It might just be a result of how I personally learn better (a series of explanations why things are done the way they are, not just letting me speculate why), and different people tend to learn differently.
The downside of this approach is that it's significantly longer, and you'll have far fewer exercises available as a reader (time and space are limited resources).
That's the approach I tried to take with LYSE. I'm not saying I got it right, or that it's better than whatever other approaches that exist, but it's the one that made the most sense to me as an author, because it made sense to me as a learner. I like that I can be guided through examples, that the person teaching me tells me "here are the possible ways to do it. I picked this one because of reasons x, y, and z", as I feel I now know how to make similar decision on my own in the future when encountering similar problems.
One of the approaches my statistics books take is to include the numerical answers in the back of the book but have a separate guide for sale if you want to know why specific approaches were taken. By being an extra book, students who need the extra help pay extra for the time to compile all the extra solutions. This also keeps the cost low for people who only need a reference.
When you say 'my', I can't tell if you mean books you've written, or books you've read. Either way, writing the solutions is non-recurring work; the cost to print the extra pages should be pretty marginal compared to the presumably > $100 cost of the textbook. To my mind it looks more like 'we get two bites at the apple', rather than saving the poor students the extra $10 to get the solutions with their textbook. Of course, I don't know how much the solutions manual costs, but I feel like this approach compromises the student's experience, when they should really just get all the content up-front.
I'll second this; the books I've retained the most from are the ones I've done the exercises for. Hell, even PragProg had exercises! Effective C++? Nada. I'm lucky if I can remember enough from it to remember to look things up.
Same here. I'll often buy a substandard book from the "21 days" or "24 Hours" series, even with all their lack of editing and inferior writing, over other books. Why? Because the exercises they usually have help me retain more that a better book.
I'm currently in the process of going through my (Python) books and making a bundle that includes assignments. These assignments are self-checking unittests. (I guess they would be akin to fill in the blank). Maybe I need to include free form assignments as well (essays).
Personally, I do most of my reading on an e-reader, in bed, before going to sleep. I think the approach suggested here would require my re-readings to take place closer to a computer.
For some reason, I never could do the exercises of programming books. When I started them, in the end I had a completely different program that solved something that affects me.
I also could never read a programming book from the start to the end. When I used the language a lot and used the book as reference, I read all the pages somewhen in a several months interval, and in some random order. When I didn't use the language a lot, I just didn't finish the book.
Nowadays the best reference is online, so while books are still good for giving me a start, there is a long time that I don't finish one.
Here's the problem I see with exercises for professional, working developers.
Are exercises useful? Yes. But doing a significant fraction of them increases your read time substantially. It pays off, but now there are other ways (at work, or in open source) to learn things that are less structured but still effective.
Exercises help you get a deep knowledge of the material, but the market doesn't reward that. You're better off with a more shallow knowledge of a lot of things.
The old cycle for learning X:
1. Get an X book. Do a basic reading to get the vocabulary and core concepts.
2. Decide if you're interested in deep knowledge of X. If yes, continue. Otherwise, terminate and choose a new X.
3. Do the exercises in the X book. This will take a while.
4. Do some X at your job.
5. Read the research papers if you want to get to the frontier.
New process:
1. Get an X book. Do a basic reading to get the vocabulary and core concepts. (Same as above.)
2. Decide if you're interested in deep knowledge of X. If yes, continue. Otherwise, terminate and choose a new X. (Same as above.)
3. Get a job doing X. The knowledge and vocabulary learned in (1) should be enough to pass an interview.
4. Refer back to the book and, when needed, read for deep detail to supplement your on-the-job learning.
5. Read the research papers if you want to get to the frontier. (Same as above.)
Step (4) of the new cycle is where the exercises would come in, but most people by that point are just trying to solve the problem at work.
New job != new company. One could transfer internally, or find a project involving X and contribute, or in the right environment, come up with a new project entirely.
If you don't have the autonomy to learn new X's as you wish, then your job probably doesn't justify aversion to looking elsewhere... unless it's paying you hedge-fund money.
Well you kind of implied new company when you mentioned passing the interview (yes, I know at the larger tech firms you can interview for other teams internally). Either way, I don't think changing jobs internally, starting a new project, etc. are trivial tasks either. If I'm content working on my current Java project at work, but I'm interested in learning some Python on the side, I don't think I should have to switch jobs/roles/companies/projects just to practice Python. Also, while I agree with you that it would be nice if most companies offered the autonomy to work in whatever technology you wished, that simply isn't the case, and not everyone has the freedom/motivation to change jobs easily.
The "typing code out" is important. A lot of us learned just this way in the early 80s, because that was the only way we could get the source: buy a magazine or a book that taught, say, game programming in BASIC, and then type in code. The inevitable syntax errors made you spend time going back through to figure out what you did wrong, not to mention the time you spent actually looking at each line.
Downloading the code from a book's web site has nowhere near the same effect, even if it "feels" more efficient.
I try to do the same thing in lectures. Unless I'm late or the lecturer is a particularly fast talker, I can usually process the information to the point where I'm writing my current understanding in my own words. Much better for me than taking dictation for an hour.
Jep, you are absolutely right. If you type everything for yourself you remember and understand everything a notch better too. If you just copy & paste you won't really look at the code...
I think I'm too ADD for this. Here's how I read programming books:
1. Open Table of Contents and find topic I'm interested in.
2. Open page of topic. Read about it. Start coding along.
3. Close book.
I feel like I can't really read them any other way. I haven't read one cover to cover in years, and that was when I was doing tech editing for publishers and I had to read the whole thing.
Am I alone? Do most of you read the whole thing like a novel?
Interestingly, if you try to force yourself to read the book from cover to cover, and you find it painful and dreary and you have to FORCE yourself to read every single page, that's a pretty good simulation of what ADHD feels like when doing an uninteresting task.
So, perhaps you could try checking out some of the advice for ADHD peeps and seeing if some of the non-illegal strategies work for you.
At first I open the ToC and go read the few stuff I do absolutely want to read about and "can't wait" to read.
Then I force myself to read the entire book like a novel at least once.
One of the great thing about reading it at least once is that once a while you'll read something you don't really think you'd need right away or that won't necessarily "click through" but, later on, you'll remember "seeing it somewhere in the book". And bam, you take the book's ToC or index and find back what you're after.
I've done it countless time with "Java Concurrency in Practice" for example. At first I read what I wanted to read the most. Then I read like a novel. Then now I use it as a "reference".
(most of the book, just like most Java books, can be dumped to trash now that I'm working with a language using lockless concurrency but that is another topic ; )
I'm more or less the opposite of the author: I find a problem first, pick the language that seems most suitable or I think I can code fastest in, and have at it. Advantages:
- Write interesting code right away, which helps me focus
- No need for a monolithic resource like a book, just Google the specific problem to be solved
- Solve a problem while learning
The biggest downside is that I don't tend to write idiomatic code: when you hack away at your own projects, they all look like your style, regardless of the source language. It took me several months to pick up good C practices at my new job, and I'm still not proficient at Ruby, Python or Java, despite having written plenty of code.
To try and combat this problem, I've started reading more advanced documents and talks in languages where I think I've got an OK base understanding. These tend to be more interesting, and better demonstrate the strengths of a given language.
First, pick up a shit-ton of books. Or o'reilly safari. Use it to quickly scan for good tools, in combination with GitHub.
Then, index the book. That is, read the most relevant chapters lightly, but read the source code closely. Make sure all the source makes sense. If it does, you're in great shape. If not, either the author is poor or you've gotta page-in back references.
Then, start hacking together code. Page-fault on the book (and others like it, including example source).
If you never learned it, how do you know if a language is good for solving a problem?
I often choose a random language for solving a small problem, so that I can learn it. It's often not the best language for the problem, but it shows what the language is good for.
For me a monolithic resource is great for getting started in a language, but most books are too deep, so I normaly don't finish them.
I find from reading blog posts, HN, etc. I have a pretty good idea of a language's capabilities. Plus, if the idea is based on a particular API where some languages are documented better or have a library already built, that reduces development time a lot. That said, you're right that I do go outside of my comfort zone intentionally when all things appear to be equal. Otherwise I never would have gotten away from PHP for web apps.
This is usually how I learn also. I find it works extremely effectively if instead of working on your own standalone project, you contribute to another project that already has best practices. That way, you can read through the source code and learn some of the conventions that are used in that language.
I am applying this methodology to Knuth's TAOCP. So far so good, as I am actually getting through the book this time, because I am just doing the initial read through. TAOCP always used to stump me when I've tried to go through it before because I normally try to understand everything I read before continuing a book. This way at least I am building up an understanding of what I need to learn to be able to understand the book.
One of the key features of Adler's methods, which he emphasizes in _A Guidebook to Learning_, is to "read and discuss". Those who have access to discussion with other learners or mentors, whether in a work or school environment, I think have a great advantage compared to those learning alone.
In developing the skills of reading, initially one may need to read stuff twice. With skill and practice, one reading may accomplish several kinds of goals at once.
At this late stage in the game, learning a new language for me is a matter of deciding on a project and building it while keeping some appropriate reference at hand. If I read a book linearly at all it's to read just enough to get the "Hello, World" going.
BTW, it doesn't take very long to become usefully productive in a language. When I hire developers who've never worked with a language before I budget 6 weeks for them to start being productive and 6 months until they're truly proficient.
Because of that, I place a higher premium on their raw talent and level of interest in the platform and type of work we have than on the particular stack they're already familiar with.
This approach really depends on the brevity of the programming books you are reading. I can't see someone leafing through CLRS, then again, then once more shortly afterwards. Or other algorithm books like Algorithms in C, or e.g. SICP or How To Design Programs. I read programming books at a glacial pace, and sometimes I find it very tough going. So tough that I would not be in a hurry to repeat the process, so I take notes. Also I find the desire to read another different book much greater than the desire to retread the same material.
It depends on your learning style. If you know any trained psychologists, they may have more to say on this, but I found a decent little article on it [1]. Reading a book 3 times and processing it differently each time probably is engaging a number of different memorization tips.
I'm not gonna argue that repeating something is going to aid memorization, but in my experience, the best way to learn a programming language is to read a book and then actually use it. If you forget things you can always look them up, but re-reading the book 2 more times is useless.
Yes, three full reads sound too much. I usually just skim it fast, then do a full read, noting interesting or hard to understand stuff. Finally I use my notes when I need to refresh my memory or to try to comprehend the more difficult concepts.
That's very interesting. I usually read once, sometimes don't even write code but I fully understand and ready to use the language. Maybe it's about the programming expertise level you already have. Of course, when reading stuff like Haskell, Scala you need to practice but when reading Python, Java... not for me.
My programming II professor would always tell us to step away from the keyboard/monitor, and physically write out a source file x times to help learn a language. There is definitely something to this process that helps language syntax piece itself together in the brain. Probably because it's similar to the process we use to practice writing and reading our human languages.
"Do the exercises" is only something you can do if you have the book. Learning from blog tutorials don't usually have that benefit. You could still use this person's approach but you'd have to substitute in something for step 3. I'd say some kind of "mini-project" makes an acceptable substitute in most cases.
This is pretty much how I use them as well, but I also intersperse personal projects in between using what I've learnt and trying to acquire new information as well. It's effective for me, I seem to retain more information this way rather than going for one pass through a book.
For reasons unknown to me, intro-level books for programming languages stopped including exercises. K&R had exercises, SICP had exercises, Dragon Book had exercises. Clojure in Action, Clojure programming, Joy of Clojure, Programming Erlang — none of those have any. What happened? Are they trying to conserve space?
</rant>