Teaching hands-on iOS development in Swift to 100 students
A hall full of stuffy air, empty coffee cups, frustrated students working on programming exercises and tired tutors explaining the concept of Optional Binding over and over again: it’s Friday, and the aftermath of our Swift introduction bootcamp is omnipresent. In this course, we teach up to 100 students the essentials of iOS development using Apple’s open-source programming language Swift. We have been developing and improving this course for over 5 years and by now manage to pull it off with a justifiable amount of time investment from the educators’ side, using tools and workflows that really make the process easier. In the following, I want to summarize the basics of the course in terms of content, roles, and infrastructure involved.
The course and our methodology
The Swift intro is a week-long preparatory course for a large project course in which students develop mobile applications in collaboration with industry partners. The goal is to introduce students to both the programming language Swift as well as fundamental concepts of iOS development so that they are prepared for taking part in the project course, which starts immediately after this intense week.
One of the big challenges we face is that participants have a wide variety of backgrounds and prior experiences in software engineering: while some are experienced coders, but have not yet developed for iOS, others only have basic knowledge in object-oriented programming. Our goal is to offer something to everyone: we want to challenge the advanced participants while not losing the beginners and giving everyone a solid baseline of skills after the course.
“Tell me and I will forget. Show me and I will remember. Involve me and I will understand. Step back and I will act.” — Chinese Proverb
Another fundamental principle of the course is the belief that software engineering encompasses a diverse set of skills which are best learned in an applied setting. We want to minimize the amount of lectures with a one-to-many transmission of information and enable participants to experience the learned concepts themselves, as soon as possible — even if that sometimes means letting students face challenges that we could have protected them from to enable them to learn from their mistakes. The course has two built-in mechanisms to achieve this:
- In-session exercises: these are small examples of the concepts explained in the session where we show the solution and let students type the code while explaining it. We either use an Xcode playground or a prepared app project for these exercises.
- Homework units: these are larger blocks of work that students complete after each session. As opposed to the exercises, we do not provide students with a solution for these. Instead, they submit their solution to a tutor for correction and typically iterate 2–3 times until the tutor finally accepts it. More on this workflow below.
Course content and session types
We have recently re-worked the course from scratch to be more coherent in terms of content. It now contains 10 sessions, 7 of which are held by us instructors, complemented by 3 tutor sessions prepared by our 9 tutors in groups of 3. The instructor sessions are divided into Swift and App sessions, resulting in the following main session types:
- Swift Sessions: Students learn concepts of the programming language using Xcode playgrounds. They complete one unit of homework in another playground, in which they apply the learned concepts on their own. Swift sessions also serve as preparation for the following App session. The linked timetable and detailed content described below shows how the sessions build on each other.
- App Sessions: They take place after each Swift session and show how the learned language concepts are applied in an iOS app. For instance, if we learn about protocols in a Swift session, the following App session will explain how delegation is used in iOS apps. Students work on the same application (an expense tracker app we call Xpense) throughout all App sessions and develop it from a basic version to a much more sophisticated app which even communicates with a simple server application written in Swift. The homework for the App sessions involves developing other, simple applications on their own (here, we give students a starting point to build on in order to allow them to concentrate on the newly learned concepts).
- Tutor Sessions: These sessions feature advanced Swift language concepts and topics in iOS development. The topics are different each semester, since we select appropriate content together with the tutors based on their interests. In recent years, we’ve had topics such as functional programming in Swift, WatchKit, UI Design, performance optimization, or data persistency. Tutor sessions do not involve homework, but have built-in exercises just like the other session types.
The course content in detail
We created an overview over the course including goals and bullet-point content for each session, which shows in greater detail how the sessions build on each other. If you’re curious, you can download it here.
The practicalities of running the course
I described the course content and methodology above, but how do we actually pull it off? One thing we often get asked is how can we get such a large number of students through the course with this amount of practical elements, run it twice a year, only put 2–3 instructors on it and not die in the process. Admittedly, it’s an intense week for everyone involved (including the students!) but we have developed a couple of mechanisms that increase the manageability of the course quite considerably. I’d like to share these for other instructors and I believe they can be useful both within and outside of the university context.
Infrastructure and setup
We set up the following infrastructure prior to the course:
- Repositories: We use Atlassian’s Bitbucket Server and set up one “Course Material” repository with read-only access for students where we push the slides and playground files prior to each session. Furthermore, each student gets their own personal repository which is only visible to them, the tutors and instructors, where they upload their homework solutions (more on the correction workflow below).
- Issue Tracker: We work with Atlassian’s JIRA as issue tracker, as it integrates nicely with Bitbucket. At the beginning of the course, we assign students tasks to prepare their own development machines with software needed for the course, as well as a task for each homework unit (the following section describes how we use these tasks to track students’ progress).
- Communication tool: We hate email, and Slack has us covered nicely throughout the course. All our tutors, instructors and students are added to a workspace and we do all communication, including both informal communication as well as critical announcements, through this platform.
- Hardware: Since this is an iOS development course, each student needs a Mac to do their programming work. Around 45–60% of course participants have their own Mac, and we provide the rest with iMacs and MacBooks that we lease for the week. However, students are not allowed to take these devices with them: we have lab times during the week of the course as well as 4 days after, during which they can access the hall and work on the devices. We also make sure that tutors are present during lab times to help in case of problems.
- Software: All development devices have to have the latest versions of Xcode and Slack installed, as well as Atlassian’s SourceTree, which we urge students to use as a git GUI.
The primary reason why we use Atlassian’s tools is the way they integrate with each other, making our workflows much easier to configure. The Atlassian Command Line Interface (CLI) dramatically reduces the time to set up the infrastructure — imagine configuring 80 repositories and 80x15 tasks by hand!
Exercise correction workflow
As described above, each of the instructor sessions requires the students to solve a larger body of work on their own and submit it to a tutor for correction. At the beginning of the course, we assign each student to a tutor who will correct all of their exercises, getting to know them in the process (each tutor supervises 8–11 students). Exercise correction is done using pull requests in Bitbucket Server.
Each student is assigned one JIRA task per homework unit they need to solve. For each homework, the student creates a feature branch directly from this JIRA issue, thus linking the commits in the feature branch to it. They finish the homework on this branch and once they are ready to submit it, they open a pull request to merge the feature branch into the develop branch of their repository, assigning their tutor as a reviewer.
We configured Bitbucket Server to require at least one approval for each pull request before it can be merged. The tutor takes a look at the homework and leaves comments and tasks on the submission. We urge tutors to comment on functionality, looks of the developed app, as well as code style and general approach of the student.
The student iterates over the submission until the tutor finally approves the pull request, at which point the student can merge the branch and the homework is officially done. Typically, each homework unit needs 2–3 iterations between tutor and student for the homework to be accepted.
The above workflow wouldn’t work without the tutors. We select them very carefully each semester, and make sure that they’re not only experienced developers, but also keen on explaining the concepts to people and helping them get better. It’s great to see how they take ownership of “their” students and support them especially as the amount of homework and the complexity of the content increases over the week. This is what the experience looks like from the perspective of Finn, one of our tutors in the 2018 summer semester instance of the course:
The motivation and curiosity of the students really surprised me — in a positive way. Throughout the course I was happy to answer all kinds of questions ranging from simple syntax errors and problems with git to conceptual questions about language design decisions and more sophisticated frameworks features.
I really think the combination of high motivation on the students’ side and really going into detail about the reasons for a specific problem instead of just fixing it is the key to having a lot of “Ahh”-moments in the course and communicating knowledge that actually sticks.
We believe that in-person help is key here, and we couldn’t run the course at such a level of interactivity without the tutors’ support and constant time investment.
Tracking students’ progress and reacting to issues
The above-described workflow along with the integration between the involved tools allows us to get a quick overview over students’ progress and only act in case of a problem. Let’s walk through it step by step.
Since the students create a feature branch for their homework from the task that has been assigned to them for the respective session, JIRA allows the issues to transition automatically on certain events. Once the student creates the branch, the issue transitions from state “open” to “in progress” and stays there until they open a pull request for their tutor to correct the homework, at which point it transitions to “in review”. The tutor and student now iterate over the homework until it is accepted and the student merges the branch, which is when the issue finally transitions to the “closed” state.
Based on these automatic transitions, we configure a Kanban board in JIRA to get a quick overview over the progress of the course. The board shows each exercise as a swimlane and the four states of issues in individual columns. This way, we can quickly see e.g. how many students have started working on a particular exercise, or who is behind and should get intensive help.
The integration between the tools also enables us to drill down from this overview to the individual commits and pull requests a student has made for a particular unit of homework. The below picture shows the tasks of a student for the course, visualizing their overall progress. Opening one particular task (in this case the homework for Session 03) gives us further insight into the student’s activity on this homework as well as direct access to the corresponding code in the repository.
This setup is the main reason we are able to hold the course with only a few instructors — we can stay up-to-date on the overall progress at a glance and only have to act in case there is a problem. For example, we will do a daily check of students’ progress and ask the 10–15% that are behind the average if they think they can catch up or whether we can provide them with additional help. It also means that we can find and warn students who are underestimating the time investment needed to finish the homework in time. It has taken us several years to get to this setup, but it was definitely worth it.
Summary and advice
I hope I described our Swift intro course in a way that other instructors can re-use some of the concepts, saving time in the process. In short, we manage to pull off an intensive coding course with a high amount of interactivity for 80–100 students with only 2–3 instructors and 9 tutors. We do this twice a year and it’s only possible because we leverage the integration between the involved tools (in particular the repository and the issue tracker) and have developed workflows for exercise correction and progress visualization that greatly enhance the manageability of the course.
Finally, here is some advice for other instructors:
- Don’t do it all at once. This setup took us 5+ years of iteration. If you are starting from scratch, pick the part of the process that saves you most time and effort (e.g. just use exercise correction with pull request without an issue tracker integration), test it and improve in the next instance of the course.
- Do not skimp on the in-person support! We rely heavily on the tutors and they play an integral part in the day-to-day execution of the course. Since the setting is quite challenging, sometimes even overwhelming for students, it’s invaluable to have actual people there who are ready to help them get there.
- Plan enough time to get everyone set up and able to access the infrastructure. We conduct a 2-hour “Session 0” in which we go through the exercise correction workflow step by step using a simple text file which the tutors comment on once to simulate an iteration. It takes a long time and there are countless mistakes that can happen along the way.
- Use git LFS if you store slides (especially large files) in version control.
- Do not underestimate the amount of confusion around git. We have had everything including students creating multiple feature branches for the same homework and merging them into each other in the weirdest patterns possible.
- Be persistent in warning students about the importance of time management, but do not micromanage them. We have a hard deadline for finishing homework to pass the course, and we do periodically warn students who are behind, but at some point they need to set their own priorities. It was hard for me to get used to this in the beginning and develop a mindset where I am able to accept that not all students are equally motivated for the course.
- It’s even harder for the tutors to make peace with people dropping out, so we need to do a lot of expectation management there as well.
That’s it, folks. Let me know whether this was useful to you and feel free to send me any questions you have — it will help me improve this article in the future. If you want to hear more about how we use Atlassian tools in our project courses, you can watch our 2015 Atlassian Summit presentation with some other use cases.
I used “we”, “us” and “our” quite often in this article, so it’s high time to acknowledge the people who were involved in creating this course along with me (in more or less chronological order): Prof. Bernd Bruegge for the methodology and for making this all possible in the first place, Stephan Krusche for originally conceiving the course and establishing a solid basis, Lukas Alperowitz for his tireless work in designing and optimizing the workflows and underlying infrastructure as well as the course content, Paul Schmiedmayer and Dominic Henze who played a big part in re-designing the course with me and also continue to run it, all of our other colleagues who help train the tutors and hold sessions as well as our admins who regularly perform logistical miracles maintaining the hardware and software involved. It’s a pleasure to work in such a high-performing and fun team. Last but not least, most of the photos in this post were taken by our tutor Florian Bodlée — thanks for continuously stalking people at work!