Building large software systems introduces new challenges to software development. Large software is built in teams over a period of several years. Typically, no individual on the team understands the entire system. Making appropriate design decisions early in the development of software can make a major difference in the ability to develop correct and maintainable software. In this course, students will learn techniques and tools to help them address these problems and develop larger software projects, improving their skills in designing, writing, debugging and testing software. Topics include design patterns, refactoring, UML, designing for maintainability, software architecture, and designing concurrent and fault tolerant systems. Prerequisite: CS 201.