|CMSC 107 (Fall 2018) at Haverford College
|Sam Lowenstein, Daniel Feshbach, Henry Mohr
|Tu/Thur 10:00-11:30 Lecture Wednesday Labs
|(L303) Tu 11:30-12:15, We 1:30-2:30, and by appointment
|Fr: 12:30 - 2:00PM (H110)
|Monday: 4:00 - 6:00PM (H110)
|Tuesday: 8:00 - 10:00PM (H110)
|Thursday: 4:00 - 6:00PM (H110)
This course is an accelerated introduction to computer science, covering the same material as both CS105 and CS106 at Haverford College. We have two broad goals. The first is to become thoughtful programmers who can articulate the methodology behind the design of our code. The second is to use those principles to help us understand the core data-structures that underlie the design of robust, efficient systems. We will do both of these by writing a good amount of code, but also thinking hard about how we can be sure we got it right.
Code is the vocabulary through which we articulate computation. We need to learn how to write it well. This takes a lot of time, a lot of getting it wrong, and a lot of figuring out what we can do better. We’ll spend the fist half of the semester learning Python, learning the core features and building up to some ambitious projects along the way.
Along with the basic vocabulary given to us by the programming language (e.g., the syntax), designing good programs requires utilizing robust, efficient abstractions for the data on which these programs operate. For example, think about how we might represent a phone book. We might implement the phone book as a large unordered list of pairs (of names and numbers). But that wouldn’t be very efficient: searching for a phone number would require combing through the list person-by-person. Instead, we might use a dictionary: an efficient way of representing keys (names, in this case) and their corresponding values (phone numbers). Of course, there are a variety of different ways we could envision implementing a dictionary. In practice, we probably won’t be writing this implementation ourselves (since someone’s likely done that for us), but we need to understand the implementation trade-offs to pick an implementation that best suits the system we want to build.
So rather than just gain superficial knowledge of different data structures, we’re going to implement them ourselves. We do this for a few reasons. First, implementing data-structures correctly is hard and error-prone, and will hopefully force you into so much frustration that you have to sit back and think hard about how the pieces fit together. When you get it right, you’ll understand the essence of programming: tackling a conceptual problem and articulating a solution as an algorithm implemented in code. Second, you’re going to need to write a lot of code to become a good programmer. This course isn’t going to be enough to do that, but our goal is to get you on a path so that you can continue in subsequent courses, internships, and your own projects.
Last, we want to write good code. We don’t want to hack something together, tinkering with it until it appears to work. We want to present a principled argument behind why our code is correct. So first, we’re going to write a ton of tests (we’ll study in the course what makes a good test). Next, we’re going to learn how to use formal reasoning to talk precisely about our code. But beyond these technical things, we’re going to talk to each other about our code—and have some frank discussions about what we should be doing better.
I hope you’re as excited for the course as I am!
Please read the Syllabus for course information.