Teaching Programming the Way It Works Outside the Classroom(cacm.acm.org)
cacm.acm.org
Teaching Programming the Way It Works Outside the Classroom
http://cacm.acm.org/magazines/2013/8/166303-teaching-programming-the-way-it-works-outside-the-classroom/fulltext
9 comments
>> My impression at school was they were teaching CS more like math, rather than aiming for anything useful.
Why wouldn't math be useful?
But yes, your professor was an idiot. Just because someone has letters after their name doesn't make them smart.
Why wouldn't math be useful?
But yes, your professor was an idiot. Just because someone has letters after their name doesn't make them smart.
I took that phrasing to mean something like:
"CS is taught more in abstract principles like data structures than actual core mechanics for something like PHP"
A former co-worker about lost it when the CEO asked "Does GA Tech teach PHP?" because one doesn't get a CS degree revolving around specific languages and semantics, but abstract concepts that surpass all languages.
Having said that, there does need to be at least some portion that teaches on the real world concepts. Things like documentation, requirements gathering, and yes specific language implementations not just whatever they decide to use to propel a class along. I've found a lot of the language-agnostic portions of the CS degree I took part in weren't nearly enough to handle the application of that CS knowledge. I had to get my hands dirty and it had to be quick.
The sad reality is, a lot of kids and people today just don't want to "get their hands dirty" and expect that a degree means they're a Ruby black belt or some shit.
A former co-worker about lost it when the CEO asked "Does GA Tech teach PHP?" because one doesn't get a CS degree revolving around specific languages and semantics, but abstract concepts that surpass all languages.
Having said that, there does need to be at least some portion that teaches on the real world concepts. Things like documentation, requirements gathering, and yes specific language implementations not just whatever they decide to use to propel a class along. I've found a lot of the language-agnostic portions of the CS degree I took part in weren't nearly enough to handle the application of that CS knowledge. I had to get my hands dirty and it had to be quick.
The sad reality is, a lot of kids and people today just don't want to "get their hands dirty" and expect that a degree means they're a Ruby black belt or some shit.
>> I took that phrasing to mean something like: "CS is taught more in abstract principles like data structures than actual core mechanics for something like PHP"
And what is not a core mechanic about data structures?
I don't agree that A) the math that is being taught is not a real world concept, and B) that syntax is so difficult once the math is understood that it elevates to the level of needing instruction. If one were to take the approach that syntax were a major differentiator between programming languages, then a 4 year degree program with gen ed requirements is not enough time to teach programming. There are just too many programming languages to be able to cover them all, and there is not enough agreement on programming languages to be able to define a core set.
All of that math is what the core concepts of every programming language are built on. The fact that these things have to execute on deterministic computers guarantees it. Syntax is nothing. Syntax should take a cheat sheet and a project to cruise through to get down. Core concepts of type theory, object orientation, functional programming, hell, even algebra, are all the same, regardless of programming language.
I see programmers all the time who are perfectly capable of satisfying the syntax, as modern compilers are very good about telling them what to do, but who have no idea what they are doing with it. They do things like call "ToString" on string objects, or ParseInt on an object that they've ToString'ed, when that object was itself already an integer.
That is why software projects fail. There is a fundamental lack of understanding of basic concepts in most programmers. They stuck to this concept that the "math isn't practical" and they code by taking random shots in the dark against the compiler. It's not because they only learned how to write a linked list in C++ and not PHP, it's because they never learned the linked list in the first place.
But, Computer Science departments around the world have been pressured to produce code factory workers who hit certain Human Resources-produced bullet points. It's because of the time taken to study so-called real-world issues of trivial import that sacrifices the fundamentals. And it has been an emphasis on graduation rates that have pressured professors to pass students who have not fully grasped the fundamentals, erroneously certifying them as trained and suitable.
HR doesn't know what makes a good employee, because most of them are pretty bad at their jobs, too. If they were any good at their jobs, they would realize that most of what makes a good employee cannot be quantified on a resume. So instead they stick to the resume bullet point mantra. Industry yells at universities for not making enough students that fit their bullet points, and parents yell at universities for not making their kids fit the hiring company's bullet point. The problem is the bullet points.
And what is not a core mechanic about data structures?
I don't agree that A) the math that is being taught is not a real world concept, and B) that syntax is so difficult once the math is understood that it elevates to the level of needing instruction. If one were to take the approach that syntax were a major differentiator between programming languages, then a 4 year degree program with gen ed requirements is not enough time to teach programming. There are just too many programming languages to be able to cover them all, and there is not enough agreement on programming languages to be able to define a core set.
All of that math is what the core concepts of every programming language are built on. The fact that these things have to execute on deterministic computers guarantees it. Syntax is nothing. Syntax should take a cheat sheet and a project to cruise through to get down. Core concepts of type theory, object orientation, functional programming, hell, even algebra, are all the same, regardless of programming language.
I see programmers all the time who are perfectly capable of satisfying the syntax, as modern compilers are very good about telling them what to do, but who have no idea what they are doing with it. They do things like call "ToString" on string objects, or ParseInt on an object that they've ToString'ed, when that object was itself already an integer.
That is why software projects fail. There is a fundamental lack of understanding of basic concepts in most programmers. They stuck to this concept that the "math isn't practical" and they code by taking random shots in the dark against the compiler. It's not because they only learned how to write a linked list in C++ and not PHP, it's because they never learned the linked list in the first place.
But, Computer Science departments around the world have been pressured to produce code factory workers who hit certain Human Resources-produced bullet points. It's because of the time taken to study so-called real-world issues of trivial import that sacrifices the fundamentals. And it has been an emphasis on graduation rates that have pressured professors to pass students who have not fully grasped the fundamentals, erroneously certifying them as trained and suitable.
HR doesn't know what makes a good employee, because most of them are pretty bad at their jobs, too. If they were any good at their jobs, they would realize that most of what makes a good employee cannot be quantified on a resume. So instead they stick to the resume bullet point mantra. Industry yells at universities for not making enough students that fit their bullet points, and parents yell at universities for not making their kids fit the hiring company's bullet point. The problem is the bullet points.
Math can be useful, but it doesn't need to be to be worthwhile. That's the point I was trying to get across. (Based on my screen name you can assume I'm a math fan) And for many programming and sysadmin tasks, the theory of computer science (and math of proofs) isn't necessary.
That said, other than the information systems sequence I took, it is the theory classes that have held well over time. Thinking about "What might make this slow?" is very tough, and the solution is frequently figuring out O(n^2) bottlenecks rather than just a tight hack in the language at hand.
That said, other than the information systems sequence I took, it is the theory classes that have held well over time. Thinking about "What might make this slow?" is very tough, and the solution is frequently figuring out O(n^2) bottlenecks rather than just a tight hack in the language at hand.
I don't know any sysadmins who even have degrees, let alone in computer science.
And I think you're short-changing the math side of it. Want to figure out who to suggest friends to each other in a social app? That's an influence graph over email addresses, game theory and linear algebra. Need to draw a best-fit curve over a graph of data? That's linear algebra and geometry. Need to be able to draw things on a map? That's more linear algebra and some multivariable calculus.
Writing just basic CRUD apps for corporate clients? They're likely eventually going to want metrics on their data, and that's going to be statistics. They'll probably be terrible at math, too. You'll need to hold their hands and tell them what they want, because the stuff they suggest will be either worthless, meaningless, or impossible to determine with the current data set.
Need to explain to a client why you need to take a week to implement a specific path finding algorithm rather than "just brute-forcing it" now (whoever the hell taught them the phrase brute-force should be shot)? You better have such a good grasp of CS that you can teach it better than it was taught to you, because if your experience was anything like mine, regurgitating what they gave us on Big-O notation is not going to cut it.
Think you can get by using other people's code doing all this? Good luck. More often, I've found the shit people post online is full of logic errors. You at least need to know the math well enough to evaluate the results of the code.
There has not been a single project I have ever done that would not have benefited from me knowing more math. The more math I learn, the more I can't believe I did without it before.
And I think you're short-changing the math side of it. Want to figure out who to suggest friends to each other in a social app? That's an influence graph over email addresses, game theory and linear algebra. Need to draw a best-fit curve over a graph of data? That's linear algebra and geometry. Need to be able to draw things on a map? That's more linear algebra and some multivariable calculus.
Writing just basic CRUD apps for corporate clients? They're likely eventually going to want metrics on their data, and that's going to be statistics. They'll probably be terrible at math, too. You'll need to hold their hands and tell them what they want, because the stuff they suggest will be either worthless, meaningless, or impossible to determine with the current data set.
Need to explain to a client why you need to take a week to implement a specific path finding algorithm rather than "just brute-forcing it" now (whoever the hell taught them the phrase brute-force should be shot)? You better have such a good grasp of CS that you can teach it better than it was taught to you, because if your experience was anything like mine, regurgitating what they gave us on Big-O notation is not going to cut it.
Think you can get by using other people's code doing all this? Good luck. More often, I've found the shit people post online is full of logic errors. You at least need to know the math well enough to evaluate the results of the code.
There has not been a single project I have ever done that would not have benefited from me knowing more math. The more math I learn, the more I can't believe I did without it before.
This is pretty much how my "programming class" goes (it is an junior college intro to microcontrollers course). We usually start with a fresh OS install, Linux, VirtualBox, Windows VM, a bunch of other stuff, lots of hand-holding, step-by-step list. It is sometimes a very annoying disaster. There are always a few do-overs, sometimes from the clever ones, usually though it is the ones who are marking time.
Show them what a file is (look at it with a hex editor). Then work through the first couple chapters of K&R. Some scripted tasks. Try to get them to notice a little bit about what's really going on. Try to get them to understand the work flow (write, compile, test, etc). Show them some common pitfalls with data types, integer division, etc. Then on to "blink" with an Arduino, (working out the bugs of introducing hardware as we go). Work through a few examples, of increasing complexity. Start working on examples with external hardware. Then they propose an individual mini-project. We keep working on Arduino stuff, eventually involving serial comms with the device via Python, or Java (Processing) while coaching them through their mini-project. Also do some, data logging, plotting their data, pushing data out to the web (Pachube/Cosm/Xively).
Several times during the semester, students will be given a task, but not given any direction (at least not at first) on how it is to be done. Some students do exceptionally well. Some "A" students wind up with their first "B" or "C" because the format/structure is completely foreign to them. Others fight tooth and nail against the format, and probably against some of the other things I do that they were not prepared for.
Show them what a file is (look at it with a hex editor). Then work through the first couple chapters of K&R. Some scripted tasks. Try to get them to notice a little bit about what's really going on. Try to get them to understand the work flow (write, compile, test, etc). Show them some common pitfalls with data types, integer division, etc. Then on to "blink" with an Arduino, (working out the bugs of introducing hardware as we go). Work through a few examples, of increasing complexity. Start working on examples with external hardware. Then they propose an individual mini-project. We keep working on Arduino stuff, eventually involving serial comms with the device via Python, or Java (Processing) while coaching them through their mini-project. Also do some, data logging, plotting their data, pushing data out to the web (Pachube/Cosm/Xively).
Several times during the semester, students will be given a task, but not given any direction (at least not at first) on how it is to be done. Some students do exceptionally well. Some "A" students wind up with their first "B" or "C" because the format/structure is completely foreign to them. Others fight tooth and nail against the format, and probably against some of the other things I do that they were not prepared for.
I tried to comment on the article but the comment form wasn't working with chrome or firefox, but:
The article is forgetting a couple of things - in the real-world you also have a purpose, a goal for what you are trying to create or a problem you are trying to solve. You also have a wealth of background and tacit knowledge about the constraints and affordances of programming. If you just had students mimic the actions of how programming is done in the real world, they would be doing it without understanding the reason for it.
Another point: none of this is new - there is actually a field of study for education research. Search for example for "problem-based learning" for more information on approaches in education that have students work on real-world, messy problems.
The article is forgetting a couple of things - in the real-world you also have a purpose, a goal for what you are trying to create or a problem you are trying to solve. You also have a wealth of background and tacit knowledge about the constraints and affordances of programming. If you just had students mimic the actions of how programming is done in the real world, they would be doing it without understanding the reason for it.
Another point: none of this is new - there is actually a field of study for education research. Search for example for "problem-based learning" for more information on approaches in education that have students work on real-world, messy problems.
We don't really need more 'hack a stack' programmers. Somebody needs to write that code in the first place, and that is the hard, but rewarding work. Teach students how to program, how to reason, how to run experiments (yes, a semester in physics lab or EE lab (I did both)), how to code in assembly, and so on, will take them much further. It's not that hard to google and download a bunch of API's, just tedious. If you don't understand why a one choice might be worse than another, you have no chance. If you understand algorithms, math, design, and so on, you will probably make a pretty good choice even if all you are doing in this specific instance is gluing a bunch of code together.
I don't think its a good idea. There's value in doing things from scratch when you are learning. It helps you learn to stay organized.
There's plenty of people who can tweak and cajole code into working. There's a lot fewer people who understand the principles behind software and can manipulate those principles to create what they want, instead of tweaking little bits of code and copy-pasting.
Yes, most of your time in industry will involve working from an existing codebase, and a lot of time will be spent cajoling and tinkering, but if you have experience building semi-large projects from scratch, that isn't hard to pick up. Going the other way, on the other hand, forget about it.
There's plenty of people who can tweak and cajole code into working. There's a lot fewer people who understand the principles behind software and can manipulate those principles to create what they want, instead of tweaking little bits of code and copy-pasting.
Yes, most of your time in industry will involve working from an existing codebase, and a lot of time will be spent cajoling and tinkering, but if you have experience building semi-large projects from scratch, that isn't hard to pick up. Going the other way, on the other hand, forget about it.
This style of programming also goes by the name "code quilting". Part of the difficulty with moving this workflow method into the classroom is that it requires schools to redefine "cheating."
Your comment about "cheating" is quite true. More specifically speaking, it's an issue with assessment in terms of confirming that a student has sufficiently demonstrated the skills/knowledge taught by the course.
For a lot of programming courses, the idea is to teach programming skills considered to be representative of various levels of ability. This is usually assessed by presenting a specific problem that requires a particular solution (i.e. program a linked list or implement the observer model). In this way, the course is treated like a math course, which is not a realistic representation of general programming work.
However, what the articles describe is something I think is attempted a fair bit by software engineering courses. The issue is though, in order to make it "fair" on students, they are generally given a problem with a couple of obvious solutions that are not too complex. Within an Australian context, there are several reasons for this:
1. We only have 12 week semesters, so a project can be approximately 10 weeks long at most. Generally students have one or two weeks to drop/enrol so projects cannot start on week 1.
2. The idea is for a course to require 10 hours of commitment by a student, with 3 to 4 hours taken up by class time. This leaves about 6 hours of individual work time, so 60 hours in total. For a real full-time programming project, 60 hours is basically 1.5 weeks.
3. Students are expected to take on 4 courses to represent a normal 40 hour week. Generally, I don't have too many friends that are expected to work on 4 projects simultaneously, it's simply not a good way to manage mentally straining activities like programming. But within a university setting, we have to deal with this reality.
4. Students are not all the same. If a project is very open ended, it's possible for students to select very simple projects for themselves and learn nothing. On the other hand, a student may attempt what appears to be a simple project, but have been tremendously challenging for them personally.
I have found this disparity occur frequently with some high schools producing students that have experience with a range of programming paradigms and design concepts, while others produce students with no background at all. Those with experience in high school have quite the advantage compared to others when you are talking about the limited level of knowledge expected of undergraduate students.
Another version of this can occur when students are given exemptions for prerequisite courses due to immigration or other graduation timing constraints. On the topic of international students, they can also come from very different cultural backgrounds and upbringings; for example, I have had students that had no idea what a stock market is.
5. Cheating and fairness. If multiple students take sample code from the same sources, it's much harder for an instructor to argue plagiarism. On the other hand, if we force students to ensure they use different sources, there exists a fairness issue with some sources perhaps offering a better, more complete solution that requires fewer customisations to solve the assignment problem.
6. Monitoring, mentoring, admin, etc. A project needs to be able to be broken up into 2+ assessments so that an instructor can identify struggling students.
If a student is given a lot of flexibility and choose something like a component based software engineering approach, with most of the time spent on research, and basically implements the wrong solution, they may end up failing the course. Alternatively, they may leave everything to the last minute and turn in rubbish for open ended projects, which require a lot of planning and management.
An instructor generally has to explain why a student has failed if the student chooses to appeal his/her grade; this is where evidence concerning poor understanding and documentation demonstrating attempts to help clarify the assessment is important.
All of the above (and really there are many more subtle issues) mean that projects need to be simple, clearly outlined, and have clear expectations and deadlines. Given that, it's much easier to avoid the whole cheating and fairness problems by constructing an assignment that do not require additional resources, or to force students to create everything from some standard set of libraries/tools.
I think wbillingsley's 100+ person project idea is very good, however, that requires a lot of work on the course planner's part. Within the universities that I have taught, the course planner also coordinates/admins, sets exams, and teaches the course. This leaves very little time for doing anything more than iterative changes to an existing course. It also appears to require relatively competent students, which is not always the case.
For a lot of programming courses, the idea is to teach programming skills considered to be representative of various levels of ability. This is usually assessed by presenting a specific problem that requires a particular solution (i.e. program a linked list or implement the observer model). In this way, the course is treated like a math course, which is not a realistic representation of general programming work.
However, what the articles describe is something I think is attempted a fair bit by software engineering courses. The issue is though, in order to make it "fair" on students, they are generally given a problem with a couple of obvious solutions that are not too complex. Within an Australian context, there are several reasons for this:
1. We only have 12 week semesters, so a project can be approximately 10 weeks long at most. Generally students have one or two weeks to drop/enrol so projects cannot start on week 1.
2. The idea is for a course to require 10 hours of commitment by a student, with 3 to 4 hours taken up by class time. This leaves about 6 hours of individual work time, so 60 hours in total. For a real full-time programming project, 60 hours is basically 1.5 weeks.
3. Students are expected to take on 4 courses to represent a normal 40 hour week. Generally, I don't have too many friends that are expected to work on 4 projects simultaneously, it's simply not a good way to manage mentally straining activities like programming. But within a university setting, we have to deal with this reality.
4. Students are not all the same. If a project is very open ended, it's possible for students to select very simple projects for themselves and learn nothing. On the other hand, a student may attempt what appears to be a simple project, but have been tremendously challenging for them personally.
I have found this disparity occur frequently with some high schools producing students that have experience with a range of programming paradigms and design concepts, while others produce students with no background at all. Those with experience in high school have quite the advantage compared to others when you are talking about the limited level of knowledge expected of undergraduate students.
Another version of this can occur when students are given exemptions for prerequisite courses due to immigration or other graduation timing constraints. On the topic of international students, they can also come from very different cultural backgrounds and upbringings; for example, I have had students that had no idea what a stock market is.
5. Cheating and fairness. If multiple students take sample code from the same sources, it's much harder for an instructor to argue plagiarism. On the other hand, if we force students to ensure they use different sources, there exists a fairness issue with some sources perhaps offering a better, more complete solution that requires fewer customisations to solve the assignment problem.
6. Monitoring, mentoring, admin, etc. A project needs to be able to be broken up into 2+ assessments so that an instructor can identify struggling students.
If a student is given a lot of flexibility and choose something like a component based software engineering approach, with most of the time spent on research, and basically implements the wrong solution, they may end up failing the course. Alternatively, they may leave everything to the last minute and turn in rubbish for open ended projects, which require a lot of planning and management.
An instructor generally has to explain why a student has failed if the student chooses to appeal his/her grade; this is where evidence concerning poor understanding and documentation demonstrating attempts to help clarify the assessment is important.
All of the above (and really there are many more subtle issues) mean that projects need to be simple, clearly outlined, and have clear expectations and deadlines. Given that, it's much easier to avoid the whole cheating and fairness problems by constructing an assignment that do not require additional resources, or to force students to create everything from some standard set of libraries/tools.
I think wbillingsley's 100+ person project idea is very good, however, that requires a lot of work on the course planner's part. Within the universities that I have taught, the course planner also coordinates/admins, sets exams, and teaches the course. This leaves very little time for doing anything more than iterative changes to an existing course. It also appears to require relatively competent students, which is not always the case.
We've had a course running for a couple of years now that seeks to addresses these issues, as well as the inherently collaborative nature of software engineering.
It's a second year course that in its first two iterations had approximately 70 students working on a common code-base: tinkering, extending, integrating their work, etc. This year we have 170 students. And we're on a path towards opening the course to the world.
(This also means that rather than have students work on small greenfield exercises, they're working on a project that in terms of numbers-of-programmers is possibly larger than some of them will work on in their first post-degree jobs.)
It's a follow-on to a more introductory programming course -- we expect students to come in to our course knowing the basic syntax of the language.
papers for those who might be interested:
Billingsley, W. & Steel, J. 2013. A comparison of two iterations of a software studio course based on continuous integration. ACM conference on Innovation and technology in computer science education (ITICSE). 213-218
Süß, J.G & Billingsley, W. 2012 Using continuous integration of code and content to teach software engineering with limited resources. International Conference on Software Engineering (ICSE). 1175-1184
(I also posted this as a comment on the article itself, so apologies if you see it in two places.)
It's a second year course that in its first two iterations had approximately 70 students working on a common code-base: tinkering, extending, integrating their work, etc. This year we have 170 students. And we're on a path towards opening the course to the world.
(This also means that rather than have students work on small greenfield exercises, they're working on a project that in terms of numbers-of-programmers is possibly larger than some of them will work on in their first post-degree jobs.)
It's a follow-on to a more introductory programming course -- we expect students to come in to our course knowing the basic syntax of the language.
papers for those who might be interested:
Billingsley, W. & Steel, J. 2013. A comparison of two iterations of a software studio course based on continuous integration. ACM conference on Innovation and technology in computer science education (ITICSE). 213-218
Süß, J.G & Billingsley, W. 2012 Using continuous integration of code and content to teach software engineering with limited resources. International Conference on Software Engineering (ICSE). 1175-1184
(I also posted this as a comment on the article itself, so apologies if you see it in two places.)
Well, I personally start most of my projects from scratch. To me, there are 4 phases to a project cycle, and the cycle is always repeating:
First, is information collection: I want to know as much about the problem as possible. I'm not even looking at code yet.
Second, is fitting that information together. This could involve code to test theories, or writing documentation to communicate them to others. I'm trying to understand how the constituent parts of the problem fit together. I'm usually working with a subject matter expert on the problem domain, as the subject matter expert on software development. I'm usually going to end up telling the person I'm working with that some aspect of their problem or how they do work--as currently stated--will be difficult to encode as a program, but a small change in business practice would make it simpler.
Third, we come to a decision on how to progress. At this point, we basically have a few proposals for how to proceed, involving some initiatives for writing code and some initiatives for changing business practice. It has to be that way. You can't write code to completely synthesize an organic process. The best human processes will seek to build redundancy into the system. The best computer systems will seek to eliminate redundancy.
And finally, we act on it. We don't second guess our decisions until we're done doing it. We don't add to it, we don't take away from it, because that would all be changing the plan without collecting new information and understanding it in the greater context.
Then we start over from scratch. We always, always need to go back to collecting as much information as possible, which now includes "how well does the current software fit our expectations".
First, is information collection: I want to know as much about the problem as possible. I'm not even looking at code yet.
Second, is fitting that information together. This could involve code to test theories, or writing documentation to communicate them to others. I'm trying to understand how the constituent parts of the problem fit together. I'm usually working with a subject matter expert on the problem domain, as the subject matter expert on software development. I'm usually going to end up telling the person I'm working with that some aspect of their problem or how they do work--as currently stated--will be difficult to encode as a program, but a small change in business practice would make it simpler.
Third, we come to a decision on how to progress. At this point, we basically have a few proposals for how to proceed, involving some initiatives for writing code and some initiatives for changing business practice. It has to be that way. You can't write code to completely synthesize an organic process. The best human processes will seek to build redundancy into the system. The best computer systems will seek to eliminate redundancy.
And finally, we act on it. We don't second guess our decisions until we're done doing it. We don't add to it, we don't take away from it, because that would all be changing the plan without collecting new information and understanding it in the greater context.
Then we start over from scratch. We always, always need to go back to collecting as much information as possible, which now includes "how well does the current software fit our expectations".
When i code like that, it can feel a lot more miserable. It is a process of constantly wrangling and finagling rather than creating. I always wonder if I should have done more from scratch.
I feel the same way. There is always that nagging feeling that you missed a corner case, or there are defects in the 3rd party code that you won't have easy access to.
We had one two semester sequence that involved a real world project of our choice, and that did involve all of the listed steps from the article. And more - we had to do real documentation: requirements, design, test cases, etc.