As a number of you might know, I have been tutoring programming subjects at my old university for a number of years now. Both C# and VB.NET and the one common theme i’ve seen in these classes is that despite having completed a mandatory object-oriented programming subject, a large proportion of students just don’t get OO. Furthermore, most of them have no real idea of how to solve a programming problem other than a very heavy, top-down method:
- Students are given a programming assignment to solve, and 5 weeks to complete it
- They look at problem at the wholistic level just to try and understand the problem
- Start designing a UI and use all the wonderful draggy-droppy components on their forms
- Spend 2 weeks tweaking their UI colours and text box alignments.
- Spend 1 week hacking together some code so that their UI starts to interact
- Spend 1 week tweaking more UI elements
- Realise there’s only 1 week left and they are missing 30% of the functionality
- Panic, ask for extensions, submit the assignment late, or all of those together.
After seeing this pattern over and over, I’ve tried different ways to address the problem in my classes. The first thing I tried was to verbally (and written in the student forums) express my sentiments that students should focus less on their UI upfront and try to make sure they have basic UI completeness first, all of the functionality implemented and finally come back to polish the UI. After all, I was seeing a great number of assignments come through with functionality either untested, totally broken or just altogether missing. Sadly my words seemed to fall upon deaf ears, and the quality of assignments were not up to the standard I was expecting.
Tackling this problem differently, last year I thought I’d try and introduce the concept of unit-testing, TDD and told them to think less about the upfront-design and instead focus on testing individual components of their system independently and build up to a solution. At the time, it seemed like a lot of students were receptive to the idea of unit-testing and test-upfront, but when the assignments came down, it looked like they just fell back into old habits and the quality of assignments seemed (on the whole) not much different to previous semesters’. After talking to some of them, I suspect the problem was that it became too difficult for them to manage this new “style” of writing their programs and keep up on top of their other coursework. The quickest and dirtiest appeared to work, and the mentality that this was purely just another assignment for the sake of passing uni seemed clearer than ever. I’m guilty of this attitude too, as when I was in uni it was more of a concern for me to make sure I completed the assignment as quickly as possible so I could spend quality time on other activities. The problem with the unit-test/TDD approach was that it offers little to a student in a reward system. Unit-tested software takes longer to write than it’s direct-implementation counterpart. This pays off in the long-run, but when your “long-run” is only as long as a 6 month semester, then why investing extra time? It’s a classic ROI question. What I needed was a way to motivate students to improve the quality of their code, and without the seemingly large overhead of the automated tests.
This semester i’ve shaken things up once again, and have dropped the unit-testing/TDD mantra. Instead, i’m focusing *heavily* on problem decomposition, units of work, single responsibility and class separation. If unit-testing doesn’t drive students to think about their application functionality upfront, then hopefully teaching them a way to make a large problem seem easily palatable will motivate them to start thinking code-first instead of UI-first. Introduction to the concept of having one class per file seemed quite foreign and unnecessary when I discussed it in our first class last week. That didn’t fill me with confidence. Despite that, i committed to persisting with this trend, and re-enforced the importance of responsibility separation under the guise of making code easier to understand, but more importantly giving the students a method for decomposing a problem and forming a solution. This I think has been the key, because receptiveness to the idea suddenly picked up when I demonstrated building a simple Guess The Number game using a number of small, discrete components. They saw what at first appeared to be a task far too large for a 90 minute class, but by identifying single functions (like “ask the user to guess a number” and “determine if the user guessed too high”) and tackling them one-by-one we produced a solution, and it’s final composition was easy to follow. #win.
I’d also changed my presentation style and was more boisterous than normal. (for anyone who knows me in person, this would be pretty intense). My theory was that if I captured their attention, it would provoke them to treat my class differently to any of their others. After all, if i’m putting the effort in, they would reciprocate, wouldn’t they? Well i’m pleased to say that after 2 weeks (yes it’s early days still) i’ve had more students hang around for the full class than before and most importantly, when i’ve run overtime nearly 70% of my students are staying back (up to an hour – 10pm at night) to ask questions and learn more.
It still awaits to be proven whether this approach makes a difference with their assignments, but certainly I’ve seen a rather large improvement in the participation of students. I’m attributing this to a combination of making the classes more entertaining, and slicing the content so it’s easily digested. Historically this has been pretty bad at university level. Hopefully this time i’ve hit a winning formula.
If you wanted to improve the ROI of unit testing all you have to do is include the tests in the assessment criteria. Sounds like you are doing a great job. I don’t remember having teachers who cared so much.
Yes and no. Yes it will start to get them to “write tests” but they’re doing it out of necessity rather than doing it for the intended purpose. A student’s motivations are very clear when you look at the code they write.
Secondly, you have to remember that everything i’m doing is unofficial, not part of the curriculum and nowhere on the curriculum radar…
…but thanks for the positive feedback 🙂
Mate, once you’ve finished teaching your students problem decomposition, can you teach me how on earth to do it??!? Please!!
🙂
Just a tangential thought: how much harder is it on a student working on an assignment pretty autonomously versus someone in a career working in a team? I suspect they wouldn’t have the same benefits of peer review or joint collaboration on the codebase and would need to spend more time winging it. Not quite sure how you address this in a class situation and the issue obviously isn’t unique to TDD but it might be compounded if trying to get to grips with multiple new concepts at once.
@Troy Hunt It’s a good question, and I don’t have an answer or even a suspected answer. My instinct tells me that firstly we need to remove other impediments which are interrupting the student’s capability to learn this content (ie: they should drop all other subjects and focus on one thing at a time). Unlike the career programmer, the student is performing 3 or 4 additional roles at the same time, and not applying enough attention to probably any of them.