He also espouses the following system of equations
Formalism First = Rigor Mortis
Intuition First = Rigor's Mortise
My position for the second course(s) is similar, and calls for practical componenent that Charlie also mentions in his paper.
However, OO programming and design is hard, and we can't expect students to master these, no matter what language we use, after two courses. We must build a foundation on which subsequent courses can build. The foundation should be grounded in the following ways:
The kinds of trade-offs inherent in using a linked list or a vector/array to implement a stack, or a ring-buffer/linked list to implement a queue are just not interesting compared to trade-offs like using balanced trees, hash-tables, or unsorted linked lists to implement a map/dictionary. We should discuss trade-offs that make a real difference in complexity.
Even with off-the-shelf software, our students do need to know how to implement linked lists/trees/... (or do they?). We must develop programming assigments that make home-grown lists better than an off-the-shelf list class. There is tension here in what we ask students to implement. For example, in C++ I think it's a mistake to talk about the built-in array type anywhere in the first two courses. However, I'm in favor of having students implement linked lists and trees. If Java is used, students are "stuck" using the built in array and vector classes.
I want students to have intuition about worst-case and average-case. I'd like students to know about different searching/sorting algorithms, but I'm not concerned that they can code these without a book, I want them to know the characteristics of a significant subset of what's found in most textbooks (as an aside, I want my students to hate Bubblesort).