Teaching PhilosophyI structure my teaching around four beliefs:
- Match instruction and assessment to course goals
- Engage students' personal and situational interest
- Provide structured frameworks and cognitive models
- Create reflective practitioners
15-313: Foundations for Software Engineering
Course StructureThe syllabus for the course takes an upside-down approach to teaching software engineering. The purpose of this is to engage students early with material they are more familiar with (testing) and use the limitations of each technique to drive the motivations of another technique which is farther from their experience. For example, we use the limits of testing to motivate inspection, the limits of inspection to motivate automated analysis, and the limits of all three to motivate design. We end the course with requirements and software process. By running the course in this manner, students can better appreciate the seemingly-softer issues of architecture, requirements, and process.
This methodology also prevents students from being attached to the waterfall process. I am bothered by courses which tell students not to use waterfall, then follow waterfall in the course itself. In many of these courses, students start by creating a requirements document, then a specification, then a design, then an implementation and finally tests. Some instructors do move up testing to the specification phase, but I feel this isn't enough to break students of a waterfall habit. Students in our course do not follow waterfall while they are learning the material, and thus are hopefully more free to move into other processes when they enter 15-413, the project-based follow-on course to 15-313.
The FoundationsThese four principles run through the entire software lifecycle, and they are the basis for every decision made in software, from high-level decisions about what features to add to low-level decisions about how to program a bug fix.
- In engineering, we can't have it all. We trade off attributes like performance versus memory. We trade off extensibility of feature A for extensibility of feature B. We trade off low cost for high security. Engineering is a very large constraint-solving problem where we must find the optimal solution among these tradeoffs.
- All of the tradeoffs lead back to economics. The question really is how much with this product cost us to build, and how much are we (as in, the company) going to make on it. Sometimes we make seemingly strange choices in our tradeoffs because it all comes back to money.
- Risks are all the unknowns in the project that might haunt us later. The problem with engineering is that we don't know all the constraints up front, so we may not find the most optimal solution. Worse, we may make a decision that hurts us later if we didn't recognize a potential risk (like our client going bankrupt, or a component of high-priority software taking too long to develop). We have to recognize the risks early and plan for contingencies in case they occur.
- Good reflection skills are a highly desirable trait in an engineer. A good engineer looks back at what happened in their project to optimize their future decisions. Did we not hit our release date because we missed a risk? Did we make a poor tradeoff decision? Reflection is about tracking what happened, analyzing it to determine why it happened and how to fix it, and then putting measures in place to prevent future mistakes. (You can even decide that it's not worth it to fix the problem! The important thing is that it be a conscious decision, rationalized by the needs for your project.) Some software processes require reflection on a regular basis; in fact, reflection is probably the most minimal process you should have on a team.
Good reading in Software EngineeringThese are general software engineering books which do not focus on a particular technology, but instead discuss engineering principles with real examples. They are all excellent for plane reading.
- Fred P. Brooks Jr. The Mythical Man-Month: Essays on Software Engineering Anniversary Edition, 1995.
- Tom DeMarco and Timothy Lister. Peopleware, 2nd Edition, 1999.
- Jon Bentley. Programming Pearls, 2nd Edition, 2000.
- Gordon L. Glegg. The Design of Design, 2009. (This is a reprint of the 1969 edition.)
- Fred P. Brooks Jr. The Design of Design, 2009. (Named after Glegg's book above.)
- Gamma, Helm, Johnson, and Vlisssides. Design Patterns, 1995. (Or the design patterns book of your choice. Get one.)
- Hunt and Thomas. Pragmatic Programmer, 2001. (There's a whole list of "Pragmatic X" books for specific topics.)
- McConnell. Code Complete, 2nd Edition, 2004. (More low-level "Thou shalt's" than Pragmatic Programmer, but a lot of people like it.)
- Howard and LeBlanc. Writing Secure Code, 2nd Edition, 2002. (Another "best programming practices" book, this time focusing on security. We've heard from industry colleagues that it's very insightful if you care about security.)
- IEEE Software
- Dr. Dobbs