Project courses in the Department of Computer Science teach students how to apply principles and concepts learned in the classroom to large-scale team-based projects and fill the gap between theoretical and experiential software engineering knowledge. CS3215 “Software Engineering Project” is such a course focusing on the design and implementation phases of the software development lifecycle. Design principles and teamwork are taught using the problem-based method through architectural concepts and the iterative development process. The course is conducted in such a way that it is impossible for students to achieve the project goals unless they follow the path of ‘best practices’ we recommend to them. In this paper, we will describe the teaching method of the project course, project infrastructure and lessons learned over three years of teaching the course.
Students learn about design principles and ‘best practices’ in many courses. However, small scale assignments do not give students enough opportunities to appreciate the value of software design principles or learn how to apply principles in practice. Further, there may not be enough opportunities to develop students’ communication and problem solving skills in the frame of small assignments. Not surprisingly, when exposed to real world pressures of industrial projects, students often find it difficult to use the skills and principles learned at the university to their advantage. Instead, students tend to perceive principles as obstacles rather than tools that can help them complete the project. Though industrial attachments offer an invaluable experience, not all companies expose students to best practices or let student teams experience the whole development cycle.
Based on our experiences of experimenting with various approaches to teaching project courses over the years, we introduced a project course CS3215 “Software Engineering Project” that focuses on advanced design by following a rigorous Software Development Life Cycle (SDLC). The ultimate goal of the course is to help fresh graduates transfer good practices to the industry and contribute to industrial projects. The application domain of the course guarantees challenging design problems, emphasises the role of software architecture and component interfaces, and involves complex data structures and algorithms. The problem is selected and scoped in such a way that students cannot meet the project goals without applying software engineering principles and ‘best practices’ we recommend to them. The course also aims at enhancing students’ communication and problem solving skills.
An overview of CS3215
The project course starts with ten lectures where a chief instructor would motivate students, clarify course objectives as well as explain the programming problem, project methodology and development process. Students do the project in teams of six students that are further divided into two groups of three students. Each team is assigned an one-hour slot per week for consultation with a supervisor. Supervisors (a chief instructor and teaching assistants) are familiar with all technical aspects of the project and share a common vision of the project course objectives.
Students spend two weeks on problem analysis and another two weeks on architectural specifications. At the same time, they develop a throw-away prototype. A programming problem—a software tool called Static Program Analyzer (SPA)—has been carefully selected to allow the two groups within each team to work on the two subsystems in a fairly independent way. As it is virtually impossible to integrate the two subsystems without a proper definition of the interfaces, we explain subsystem-level SPA decomposition to the students, and their task is to follow up with component-level decomposition and specifications of major component interfaces. At the same time, the interface is complex enough so some changes and refinements of interfaces are inevitable during development iterations. To cope with that, students must work together during architecture design and meet regularly during project development. Students also develop communication skills as they learn how to schedule meetings and how to write documentation in a way that other team members can understand.
Students develop the project in iterations. This process helps students tackle the difficulties one by one, applying principles of separation of concerns, abstraction and refinement. Program reliability (close to industry standards and achieved by reviews and comprehensive testing) is emphasised throughout the project. Students are advised to allocate enough time for planning and testing, to make unit testing an integral part of development and to do integration testing and system testing often, at least at the end of each development iteration.
We provide students with a project handbook that includes a problem description, compendium of recommended software engineering practices for the project, sample solutions illustrating how we expect them to approach design problems and technical tips. At the end of the course, students write a report, present their solutions and we test their programs for errors with an auto-tester. We use automated clone detection tool to find (very rare) cases of students copying solutions from other projects.
Evaluation of students’ projects
Students’ projects are evaluated based on the scope of the programs’ functionality implemented, programs’ quality attributes (e.g. reliability, reusability, extensibility and the efficiency of a query evaluation strategy), and the quality of project documentation.
At the end of the project course, each team is given one hour to present their work and to complete a final system testing. One test run consisting of 200 to 300 test cases covering a large set of functionalities is executed for each team. Important information such as failed cases, exceptions and timeouts (when the time taken to evaluate a query does not meet the time limit we set) are captured. Any test cases that failed are then re-run and the results are verified manually. Students are allowed to give explanations of what went wrong if they know the reason. Hence, the final testing will give us an objective score on the reliability of the students’ programs.
To facilitate the final system testing, we developed a tool called AutoTester (a server) to automate testing of students’ programs. The AutoTester works with students’ programs according to a client/server architecture concept. The AutoTester reads a set of test cases (program queries in our case) and then repeatedly sends queries to a student’s SPA program (the client). The SPA evaluates the query and returns the results back to the AutoTester for verification. To minimise problems that might occur during the final testing, a trial run is conducted for each team prior to the final testing. This not only helps to familiarise students with the testing procedures but also highlights any problems the team might have when using the AutoTester.
From the statistics of the project course, most teams manage to keep their total number of errors below 10. We believe that our relentless emphasis on reliability manage to drive home to students that testing is important in any large scale software development. We also make the following observations:
- In most teams, at least one unique failed case is attributed to the team’s misunderstanding of the specification. Some teams purposely imposed their own restrictions on the project to reduce its complexity, and thus failed to meet our project requirements.
- Programs implemented in Java have fewer total errors because Java is a programming language used frequently for programming assignments in most courses in NUS and hence, students are more proficient in using Java than C++.
- C++ programs tend to have many timeouts but there are a few exceptions. We believe that the lack of error checking mechanisms in C++ forced our students to be more conscious about error/exception handling and recovery when implementing in C++, resulting in fewer exceptions. However, as most of our students are exposed to C++ for the first time, they tend to code in an inefficient way, resulting in more timeouts.
Results so far
We have been offering CS3215 since 2001, to 80–130 Computer Science students each semester. At the end of the project course, students grow to appreciate the role of software architecture, learn how to communicate in terms of interfaces, learn how to split the project work and how to document the products in a clear way that other team mates can understand. Most of the teams became very much involved in the project and were motivated to work hard in order to deliver a quality product. Though we make little effort to emulate the real world in this course, we believe students have learned some essential skills that will help them deal with real world project challenges in a systematic rather than chaotic way.
Improving students’ communication skills is a major concern and focal point in our project course. The ability to translate solutions from the concept level to a proper document design, to code, test plans and other program artifacts, to describe interfaces, to use assertions, as well as to prepare and conduct team meetings in an effective way, are all communication-related skills. Communication skills integrate the essential human and technical aspects of software development. As students do not have enough opportunity to develop communication skills in assignment-based courses, it is a major issue for the project course to address. We believe the course has given students ample opportunity to experiment with a wide range of techniques to develop and master communication skills.
The project infrastructure also plays a critical role in achieving teaching goals. It helps students learn about software tools in a short time and helps instructors evaluate program solutions. A common problem in many universities where project courses are offered to a large population of students is finding enough qualified faculty members and teaching assistants to supervise them. Our teaching approach and the project infrastructure have alleviated these problems. The project handbook and project infrastructure communicate to students the ‘what and how’ of the project. There is a repository of project information shared among instructors, thus shortening the learning time before new instructors can advise student teams effectively. The project handbook and project infrastructure can be used as it is or customised to account for specific goals, student audiences and specific qualities deemed important in a given offering of a project course.
In summary, we find our approach to teaching the project course enhances students’ teamwork and communication skills, helps them apply principles and ‘best practices’, and deals with practical problems related to teaching a project course for a large population of students.
* This article is an abridged version of a paper presented at the 18th Conference on Software Engineering Education and Training in Ottawa, Canada, 18–20 April 2005.