This is pretty much how I taught my High School Computer Science classes.
The biggest step for me was to never touch the student keyboards. And then I basically only answered their questions with more questions.
Sometimes I would hear students grumble "He never answers my questions...", But in the long run, they would start asking themselves the same questions they knew I would ask (what did you expect it to do?, what did it do?, Why did it do that?)... Then they would usually solve their problem without me!
Or, when they called me over they would start with "I tried a, b, and c" and got results x, y, and z" which is a way better start to a learning experience for everyone than the old "it doesn't work, fix it, please"
I personally think this is bad advice. I've experienced this kind of method through a friend of mine; it was always more frustrating than it was worth. I knew he has good intentions, but the truth is, different people learn differently*. When I ask questions, its often to try to build context or a mental map before I tackle a problem. I think that, while being cryptic and only answering questions with more questions can help nudge certain students in the right direction, it will just frustrate and confuse others. My guess is that for every student you've found this method successful with, there were 3 students who just gave up on asking you for advice because they'd just assume you'd elude them again -- and these are invisible failures.
Personally, I stopped asking that certain friend for advice after one too many frustrating sessions.
That really depends on what you want this certain friend to do. Usually, when the context is not learning, you want to hear answer with the nuts and this is universally true.
We don't comment on code review with "What do you think this does", we say "Here this is wrong because it will do X and to fix you need Y".
But when it comes to learning, I can't fault the other approach because that is clearly the better way to drill the programming mentality over to the learner. Almost all good engineer knows where to look, and syntactic or logical problems in any context are solved in a very similar way. People who don't have this structured method to approach a bug are going to find trouble in software engineering.
If the change is simple, i.e. obvious with an visual examination, or if the bug is straightforwardly presented in the stack trace, in a learning context it's imo more helpful to have you go over the problem and arrive at that conclusion yourself.
I've had multiple instances with multiple different people that come to me with problems that are pretty much repeats - I've since adapted to "I'll give you hints but you'll need to figure out yourself" in the context of learning.
Yes, I don't disagree that sometimes toiling over a problem yourself is the most rewarding. I think most people have experienced this. This is the purpose of exercises in textbooks. But most textbooks don't solely consists of exercises. I was responding to this idea of never giving direct answers, only always posing more questions, which I think has a high potential of backfiring. As another user pointed out in this comments thread, I believe the best approach to take is first get an understanding of what the student already knows and understands, how best they learn, and form your instruction around that.
When it comes to working with people, it’s usually clear who learned programming by rote memorization and who actually noodled their way through a formal education. I’ll do almost anything to avoid working with the former. They just can’t carry their weight, most of the time.
> the truth is, different people learn differently
This is the same conclusion I came to as a computer science TA in college. At first, I was naive and tried to teach people the way that I would find it effective to be taught, and I was a bit stymied by this. I slowly started trying different strategies for teaching things, and once I made the (somewhat obvious in hindsight) realization that different students learn in different ways, it became a fun challenge to find a method that worked for a given student.
I'm not a teacher, but a parent of young children. Echoing an educational scientist from my country: the key point for effective teaching is to realize how or what does the student or child understand right now. This should be the baseline of your explanations.
When I tutored computer science at the community college, I often felt like some of our students were constantly trying to trick me into writing code for them. Idk if other tutors often did that for them or what, but it was frustrating for me.
Avoiding getting sucked into touching their keyboards was what I had to do, too.
I don’t mean to sound cynical, but it’s possible that these students simply got away with this strategy for their entire academic “career” up to that point. I.e. complain about the difficulty of the task, throw your hands up, ask for “help” enough times until the teacher basically solves/explains the entire problem for you and then just copy their exact solution.
The idea that a teacher should ever touch a student keyboard in a computer science or programming class to me is absurd.
> The idea that a teacher should ever touch a student keyboard in a computer science or programming class to me is absurd.
I agree.
In this case, the students who seemed to work this way were mostly (all?) ESL students, and none of the tutors spoke the native language of the students. So it could be difficult even to indicate what you wanted them to look at, and it was especially frustrating when the errors they were dealing with were trivial syntax errors.
I would see this a lot, too. I think in many cases it is a coping mechanism that they develop and may not even realize they are doing it.
You see articles about not praising kids for being "smart" because that praises something innate about them, but instead praise them for working hard or growing or learning. Sometimes kids that are "smart" in middle school don't have to work/learn/study because everything just makes sense. But then they get to high school and their grades start to dip because their "middle school smarts" don't apply to high school material and they didn't develop the skills to study/learn effectively. But they are known as "smart kids" and smart kids get good grades... So they need to find ways to get good grades... because they are "smart kids"
I hope I was able to help some of those students unlearn some of those habits and develop more educational ways to "get good grades"
> Sometimes I would hear students grumble "He never answers my questions..."
Did you ever explain why you are doing this? After walking a student through their problem I would praise them and point out they solved the problem themselves. Some people may perceive your style as you being annoyed or unwilling to fully help, so explaining explicitly why you're helping that way would be good.
Yeah, I don’t see the point in just stubbornly only responding with more questions. As an instructor you could actually instruct. Why not say “a good technique when you get stuck is to ask yourself these 3 questions…” instead of just cryptically asking the questions and hoping they come to this amazing epiphany that wow my instructor wasn’t just being cryptic because they’re a jerk, they were doing it to teach me!
I absolutely hated primary/secondary school until I realized all these "difficult" methods were designed to help ME learn.
Naturally the attitude at that age is "Oh my gosh the teachers love torturing us >:( they hate us >:( school bad >:(". I'm forever grateful for the gifted program at my district for teaching me otherwise. Writing this comment gave me a rush of nostalgia, I think I'm gonna go visit again
Yes, it took me too long to realize this too... so I immediately told my kids this is the reason for all of the exercises they have to do. When they approach it from the perspective of its purpose, then they take the time to learn it rather than just trying to finish it.
Did you find that this method resulted in less, more or the same number of students that just couldn't follow? I've been thinking about this a lot as in France we have a few "alternative software school" that use the "basically figure it our yourself" method a lot, and while it's sometimes frustrating as an experience, it really prepares you well for what you're going to face.
I intuitively think one flaw would be that less student would be able to finish the studies, but on the other hand these students wouldn't probably make it in the professional world either.
I can’t speak for the person you’re replying to, but I suspect the idea may be that the students are able to “make it” in the sense of holding down a job, but not in the sense of being particularly competent / productive.
That's a good talk, and people should watch it. But as I recall (it has been a bit since I watched it, probably 6 months) she doesn't argue that we should only give answers to students, but that we should give more answers to students than many (especially self-taught programmers) might think necessary (or desirable).
The research basically showed that rote learning (the thing so strongly objected to here on HN in many education discussions) is actually effective. But that doesn't contradict the idea that self-guided exploration is bad (paired with an instructor answering questions, even questions with questions), it just shouldn't be where we start or the sole way we teach.
In particular, a common objection to rote teaching programming is often along the lines of, "I taught myself assembly on a Commodore 64, anyone can do it [and I'll imply that it's the best way to learn]." Which can work, and can work for many students. But it's not effective for every student, and creates an artificial barrier (for the majority of students who will learn better, faster, or even at all with a more traditional presentation of the material).
I made it a point that "if it is on an assessment, then they will have seen it in class"
No tricks, no novel algorithms. Just show me that you learned the things that I tried to teach you.
If a lab asks you to write a for loop that prints all the strings in an array, then I've taught the syntax for strings, printing,accessing elements from arrays, getting the length of an array, writing a for loop, etc... There have been hands on activities and/or funsheets for each of those ideas that include fill-in the blank questions where they get the framework of for loops with arrays.
And they get handouts with the syntax / code structures / algorithms.
And they get those worksheets/handouts/etc to reference while working on the lab.
In a classroom environment, it's important to teach and build the foundation to solve problems. But then it's important to make the student do the work to build the connections so they actually learn something. Even if the something they learn is where they can look to find the answer to a question like "does an array start at 0 or 1?"
In my eyes learning to programm is on of those things that is a out a stract connotations or ideas how we think something functions much more than actual experience.
When you learn gravity, of course you can watch an apple falling from a tree and fogure it out yourself. But you could also watch an apple falling from an tree, try to figure it out for a while and then get a fascinating deep dive in the physics behind it, and then take another dive at the issue.
Just by presenting the issue in the right way instructors can make the difference between people who struggle to grasp something and people who already have the right abstractions in their head but only need to figure out what it means in practise.
The worst peogramming instructors are those who are like: "It was nearly impossible for me to learn this, why do you think it would be easy?"
I still think there are also questions which are best answered straight, like 'how many bytes does a float have? Do arrays start with 0 or 1 in this language? Is printf of %s with null argument, undefined behaviour, implementation defined or actually standard conforming'.
You've been down-voted, but you're absolutely correct in some situations.
Sure, answering those questions with "this is a great opportunity to learn how to read the documentation" is the "right" response.
But I think we've all experienced the frustration of trying to write something in a language we don't use every day, and 'wasting' our time looking up simple things ("okay, what's the exact syntax of a for-loop in this language again?") that just adds friction when we're trying to solve a problem. There's a reason programmers complain so much about being interrupted.
Part of being a good teacher is being able to make those points of friction disappear and enable your students to "get it" and experience the joy of solving a problem.
Don't let perfect be the enemy of good. How many kids would play football/soccer if you were only allowed to play a match with regulation numbers of players on each side, and stopping play every time someone didn't have 'perfect' form?
I suspect they were downvoted because the initial commenter didn't say they only answered questions with questions or that they never provided more traditional instruction. GP is arguing against something that wasn't even said.
Those kind of questions are a great opportunity to show a student where to find documentation and how to read it, because that is a daily journey that will never end.
"How many bytes does a float have?" is a bad question to ask. Languages may implement floats differently. If someone asks "how many bytes does an ieee 754 double-precision floating-point have?" then sure, answer 8 bytes. But "how many bytes does a float have?" is precisely a question that should be further defined.
I think this method of teaching works well if this lines up with how the students are evaluated. The students willingness to accept this form of teaching is entirely reliant on how they feel this will impact their final grade. That's why it's important to align your grading and evaluation style with your teaching style if this is what you expect from students. That way, they'll be more inclined to go with the flow knowing that it won't bite them on the other end when it's time to take a test.
That's an excellent point. I actually stopped grading lab assignments. I found students were more interesting in getting "the answer" than learning the material. This would lead to students making decisions that optimized for"having the answer" but were detrimental to "learning the material".
Once I stopped grading the labs, it freed students to experiment and learn rather than rush and stress about the due date. It didn't really matter if they finished the lab, as long as they learned something along the way.
There was, of course, much more to my classes than the labs. Lectures, group activities, "kahoots", discussions, prelabs, funsheets, etc... Lots of ways to assess a students understanding and help catch the ones that are falling behind.
As a CS teacher, I think there is a time for touching a student's keyboard and a time for leading them with questions or some other method. You have to read the student. With weaker student's I will sometimes set them up with a partial answer and get them to complete it, or show them multiple solutions for a similar problem, hoping one will spur on insight.
Some people learn better by doing and discovering, others better by initially imitating and still others in different ways at different times.
For me there are no preferred methods, just a toolkit I build on and pull from as I learn more about teaching.
This works if the student already has a grasp of how to write software. The new teacher here does your method with new students just learning the syntax, and it's a failure. Treat them like they're learning french. First comes meaning of words, then how they're applied. Examples of it, what it means, and then how you change what it means to mean something else. Practice and Exposure is the only way to effectively learn any language. These students are going to entirely forget what a for loop is after their class and switch majors when the next classes depend upon fluent understanding.
this is so true! my brother started learning to code later on in life, i knew he looked up to me but also, he knew he could ask me for help whenever and i helped him as best as i could, but i get busy working on projects and cannot always answer a text message or phone call. i would see his message later on in the day and listen/read his messages and it would start out asking for help and about the 2nd or 3rd and sometimes 4th message he would have it figured out and i was happy about that because he did what i think is the most important thing when it comes to long term mastery of any skill
he figured it out on his own or was at least was able to recall the knowledge from within. if i would have took over his keyboard he wouldn’t have imprinted that as fast, i heard this saying once and it’s encouraging for others to hear/read as well so i’ll say it
“when you are confused, don’t be upset at yourself, it is a good sign. confusion means you thinking about something new or from a different perspective, and that means you are learning”
it’s a humbling experience, i get it, but not a sign you will never understand something, in fact, confusion is the first sign that you are getting it. be encouraged
> Once you understand how it works, it’s extreamly challenging to imagine not understanding it. This can be problematic when teaching because it creates a gap between teacher and student. Even the most empathetic teachers can’t quite imagine themselves in a student’s shoes.
This reminded me of my old engineering tutorials. Where I went to uni you have these 2/3-on-1 sessions with a tutor to go through a weekly sheet of questions across subjects.
After a short time, we came to the conclusion that the more decorated the tutor, the less good they were at teaching. I had people spanning from just-started PhD students to professors who were members of various academies. The more letters they had after their names, the harder it got to pick up anything from them.
The professors had a couple of things going against them. First, they were no longer warm hands. Too long since they themselves had to analyze transistor circuits. They might know something about how the state of the art is done on an industry grade computer, but no way they could go back to hand drawings of toy systems. They also probably wouldn't know quite how to operate that state-of-the-art system themselves, but trust a postdoc to do it. Second, they were busy. Really really busy, mostly with the business of running a lab. A lot of not-analyzing undergrad level transistor circuits. A lot of grant proposals.
So when you got one of these highly decorated people slumming it with the undergrads, they just wouldn't know what it is you didn't understand. The best were people who'd just done the course not long before you, and understood what to say to trigger you to think the right way. They'd been down the same dead ends, the same oddly worded questions.
This is why I'm no longer so interested in my kids having a lot of professor time. You often hear people complaining their expensive degrees are taught by TAs, but in the end the professor guy would not do much better for the kid.
Something that shocked me was that when I was trying to teach a scripting language to some non-programmer sysadmin types, they kept getting stuck on what I thought of as minutiae.
Things like the difference between single-quoted and double-quoted strings. Special character escapes. Etc...
One person was confused as to why I kept using different kinds of brackets -- round, square, and squiggly.
To me, these basic idioms are so ingrained, that I simply didn't even think to explain them. Of course the squiggly brackets create a nested scope! What's a scope? Uh... that isolates variable names so they don't clash. Why can I refer to the same variables across those squiggly brackets but not those ones? Well... umm...
Oh man, I'm running into this just teaching my kids to read. English is a shit language to speak natively and then try to read. When starting, words like "people" you read like "pee ah pull" - there are so many words you have to "just know" how they're pronounced and learn that the word you're reading connects to those sounds even though the letters don't connect to the noises you're making.
Where in Spanish, once you know the rules, you can read the language out loud without knowing what you're even saying.
Likewise with programming, a language that relies mainly on symbols takes a lot to learn when those concepts don't even exist in your head. What's a function? An expression? A token? An operator? A scope? The best thing to do is use a language that doesn't make you know all those things at once to get started.
This is like learning natural languages like French and mandarin. In school they make you do spellings and all the words need to agree in tense, number and so on.
So you think that's what the language is, a bunch of picky rules.
You need a certain volume of material to see the real picture, and a novice won't have that.
This is all solid advice. I also note that new managers of programmers should read it as well. Managers feel the weight of the responsibility for the project and when one of their engineers is stuck it puts the schedule at risk. For new managers especially, their instinct is to just tell the engineer how to fix the problem.
That solves the near term schedule risk but does nothing to prevent recurrence.
When I'm managing software engineers I try to make it really really clear that getting stuck is a "known" thing and getting unstuck is a "learned" thing. So to come to me early when they are stuck so we can practice ways to get unstuck. If they wait too long to ask for help, it is a much bigger problem. (and when I am programming for someone I can be just as bad at not asking for help soon enough) for one of my employees who was an ex-marine and really really didn't like asking for help, I got him to think about it as asking someone in their unit to provide covering fire, that is "help" and essential to achieve the objective. They understood that reference really well and we got along great after that.
My point being that everyone is a teacher to somebody, so when an article that frames the teaching as instructor to student, don't make the mistake of thinking it doesn't apply to you. There are things to learn in there.
Hell, it’s Saturday and I feel talkative. If somebody is stuck, several steps come to mind:
Do they understand the problem(s) they’re being asked to solve? Toy or otherwise, this strikes me as a necessary condition.
Can they express their solution in discrete steps? Software is brilliantly stupid, and must be told in detail what to do. This step should be independent of language, and is more of a logic exercise.
Can they express their “discrete steps” in the language(s) that are required. This is an engineering problem that can be solved with references, practice, etc. Perhaps we can think of the steps stage as writing in ones native language and the implementation stage as writing in a nonnative tongue.
Debugging. This is a generally applicable skill for any multi step problem. In the case of software there is language and hardware issues in addition to logic and understanding the problem space that usually make things worse. But I have found that if these two aspects can be separated things go much better than blurring the two.
If needed, tuning can be seen as both a (re)design or additional debugging step which is outside the initial discussion. But aside from design, one should separate making something work vs. work fast unless they have a very good grasp of their problem and solution. Much of what we do is separable, as things like abstractions are so useful.
If a student is struggling, the mentor can help them determine which step they are hung up on and the kind of nudging that would be most helpful. People who can create sound, stepwise solutions are useful - they can apply this to pretty much any environment. Knowing the nooks and crannies of a language without good logic/design merely creates hard to maintain code.
A lot of this is mirrored in "Code Complete" -- especially the part about expressing a solution.
Most of it was self-evident information you would naturally pick up, as you made your way through your "programming journey," but the parts about planning were the ones I took copious notes on (and integrated into my own craft).
If you don't know -- exactly -- what problem you're solving, then you're either gonna sit there dumbfounded, unsure of where to go from there, or you'll frenetically start brute-forcing the problem, trying -- sloppily -- everything you can think of.
It never really occurred to me before I read that book that writing the actual software shouldn't be just about 95% of the process. ~40% should be planning: understanding the problem, understanding the tools you have available, and building out a rough outline of how everything's going to work (preferably in pseudocode comments you can then convert into actual code).
Or that you could write code without painstakingly testing every few lines to make sure you "did it right" a la code cowboy.
Wasted a lot of time, and spent too many nights up on caffeine trying to force my way through a problem (albeit it usually worked, with the cost of having to rewrite everything ;).
Yup. That was on of the books I read, along with the pragmatic programmer and other most technical, Unix-y things. People always said I was a step by step kind of guy and that seemed to map well to programming/hacking. Although it helped seeing external reinforcement to solve things ina logical manner without skipping steps.
> you could write code without painstakingly testing every few lines to make sure you "did it right"
This technique would eliminate many of the bugs I create (mostly careless mistakes), if I could be bothered to do it, so I'm surprised to see it presented in a negative light.
If they're basic typos/syntax, having something like Rust's "cargo watch" running in a terminal to rebuild files that have changed can be useful. Usually, when I'm done writing a big abstraction, I'll do a quick proof-read, and then go maximize that terminal to see what the compiler found.
A heavy-weight IDE would also serve that purpose. But, I personally cannot stand all the distractions they introduce (drop-downs, red lines, auto-complete shadows, etc.), so I stick with emacs, and just run my unit tests after I'm done writing a big logical block.
If they're matters of logic/constructs/and such: I've found reasoning about in my head the piece I'm writing, first -- and understanding exactly what it's going to do and how it's going to do it, before I even start programming -- to be useful in preventing bad code.
The main problem I've had with "code a few lines, test, code a few more lines, test" is that it always pigeon-holed me into thinking tactically, rather than strategically.
"OK, I gotta write a class that handles X, Y, Z. How's that gonna happen? I don't know. The compiler is a fickle mistress, so I have to focus on getting it to work at all first, before I even think about the grand scheme of things."
When, I could've just written the whole piece in one go, and then dealt with my lexical errors. As long as the logical expressions all make sense, and I understand what my code should be doing, I can make small adjustments here and there.
Dealing with the interpreter/compiler is a distraction, that's best left to a dedicated chunk of time to go over all my errors -- so I can learn from them, and not just give them a quick patch, and move on to the next challenge, without really reflecting on why I had errors.
Weird, I seem to mostly not have that problem, and vividly remember the confusions and mysteries. I’m constantly jumping in to improve others’ explanations that assume too much. I’ve started calling myself “the translator”.
All the best teachers I've worked with have this skill. I use the "translator" analogy as well.
Though I've found it's not so much "remembering" the confusion and mysteries from your own past, but paying very close attention to the student(s) so you notice as soon as there's some divergence in their mental model from what you're trying to relate.
Stop, slow down, address the assumptions you didn't even realise you were making, and it's amazing how much complexity and knowledge you can seemingly transfer into someone else's brain.
Of course they'll forget 2/3 of it over night, but it's easier next time, and once they've "gotten" it (and the corresponding endorphins) once they've got way more motivation to keep going.
> paying very close attention to the student(s) so you notice as soon as there's some divergence in their mental model from what you're trying to relate.
Yes! I call it “finding the NePoCU”, Nearest Point of Common Understanding.
Edit: or rather, the technique I use to identify where I can start explaining from.
I've realised immigrants, expats, bilinguals, and just anyone who has lived experience at the interfaces of different cultures are particularly good at this.
When you're both speaking your non-native language in a murky context you 'negotiate' back and forth, using simpler and simpler language (and hand gestures!) until you both agree you're at the NePoCU, and then you slowly build back up and have a great conversation. It's how things like pidgin trading languages emerge.
And of course it's a fun time because you both feel a little ridiculous struggling so dramatically to explain such simple words. Have those conversations in a bar, or over cups of tea, and you'll make some great friends and get invited to 'real' local events :)
My teacher in both my Architectures and AI courses had this bad. Still to this day have no idea how any ML works in python or what the purpose of keras is or how it does any processing. Or why certain 1's and 0's churned out of a breadboard.
All I can tell you is that I learned nothing and just paid to get them done.
After teaching fullstack at a well-known university for a year and tutoring many students I feel that about 90% of them will never be competent entry-level programmers.
There will be much disappointment ahead for the thousands (and thousands) of people being steered towards coding instead of to some more appropriate job (of which, I recognize, many have left the country).
> about 90% of them will never be competent entry-level programmers.
What's crazy is that I feel the majority of people I interview/phone screen would not be a competent entry-level programmer, and they've all had at least 10 years in industry.
I’m not saying that you are or are not, because I don’t have any context, but consider that your feeling might be wrong. I mean, there’s the real possibility that you are a bad interviewer or a bad phone screener or whatever. Again, not saying that _you_ personally are. I don’t have the information to know. I’m just pointing out that it’s the moral equivalent of “if everywhere you go smells like the dog went poo, maybe you should check the bottom of your shoe”
The reason I point it out is because if the industry is going to actually get better at interviews (something we generally agree needs improvement) then we have to continuously challenge the assumption that we are actually good at interviewing when it’s our turn on that side of the conversation.
IME, they get into companies that don't fire people (or government jobs) but rather move people to other projects, or they bounce before they're discovered to be incompetent. Companies often won't make stronger statements than "X worked for us on these dates" (the company, individual recommendations may be different). Barring legal trouble you may have caused, if the issue of departure is primarily performance, they don't want you suing them for making unprovable negative statements about you.
That's a pity inasmuch as it punishes those who have done well on a job. I would really appreciate it if when checking references a past employer would feel comfortable saying good things about my work.
In the US, get rid of our sue crazy nature. Then we might be able to have nice things again. Or get specific letters of recommendation from your past employers/managers, they'll provide those if you perform decently. You'll probably have to go to a specific manager, though.
I think many companies are largely dysfunctional, driving top performers away (or never hiring them in the first place) while keeping people who copy/paste and fumble toward "good enough for this sprint".
> If you find this useful, let me know, and I’ll write another one about helping students who are pair programming.
Just want to say, I found this very useful! This is a problem I’ve been trying to solve recently, with only some limited success. (I also want to second the other comment about providing an RSS feed.)
I do a lot of one-on-one programming teaching, and this really hit home with how I approach teaching. I especially liked the following:
> You’re not a machine. Every teacher and every student is different. The art of teaching is finding a technique that works for the situation at hand.
Just knowing something (like programming) isn't enough to be a good teacher. It really is an art that takes time and caring to develop. Thanks to the author for putting my thoughts into words so well!
HTDP has a nice 7-step process to designing programs and suggests teachers ask the student to point to which step they’re stuck on, to help formalize it a little bit in their minds. I quite like it.
Is there a general process for solving problems? These last 25 or so years I've been programming I've mostly just been thinking about the problem until I have a solution. Sometimes I go for a walk but that seems pretty hit-and-miss.
My process seems to boil down to not realizing I was supposed to get frustrated and give up.
I would strongly second the GP's recommendation. The book mentioned is aimed at math teachers up to an undergraduate level, but generalizes quite naturally.
The idea is that one may induce a path to solution in a student by stripping a problem down to it's knowns, unknowns, and constraints so that it may be comprehensible, then connecting these elements back together by asking pointed questions that could have conceivably occurred to the student. He gives plenty of practical examples of how one may dial the complexity of these questions up and down, how to relate by analogy, and plenty of other techniques for approaching problem solving generally all in a flimsy paperback that can be finished in two evenings in a weekend.
The most impressive part, to me, is that nearly every example is both illustrative enough to be a word-for-word guidebook for math tutors, and accessible enough for even a middle school student studying Euclid to understand in it's entirety.
I don't understand your question, I didn't say it was just a matter of following this algorithm or process described in the book. You also have to possess the base knowledge that feeds into it, which is described in the book in a mathematical context.
Even then, it's a set of heuristics and guidelines. Neither the book nor my comment claim it to be truly universal.
Not really, but HTDP has a nice boilerplate to frame problems for a computer program. You're not going to find the sterile neutrino by following it (probably), but you're going to be able to go from a simple cli tic-tac-toe to consuming APIs in a non-trivial CRUD program with it.
This may be good advice for programmers that learned in an academic setting, but as someone that taught themselves this would drive me nuts. I still struggle with abstract problem solving in problems that I haven't solved before. A lot of algorithm based interviews I'll totally flunk the first time around. Depending on the interviewers behavior I've either bailed out from there or tried to learn something.
More helpful is backing up and framing the problem to be less abstract. When learning to code, we're learning new ways to represent things that we likely already intuitively know. In that way, you're teaching expression. The two are taught very differently, imo.
As someone who is also largely self taught in cs terms, it's actually very amazing to me how even very abstract ideas which seem to be very far away from a "solution" to a "problem" often fall into place very nicely.
For example consider a unification algorithm (e.g. https://reasoning.page/29021/unification-sort-of-in-rust which is an explanation of it that I wrote). The individual parts of it do not seem that spectacular, and also seem quite abstract. It is so simple (in my mind) that it could not possibly be correct. However, there is an emergent property when the interactions between the different parts of the program are taken together.
I think what a lot of instructors fail at is they don't give students a working example of how something works. Sure you're not really going to learn, but what's the point of me having a half-assed assignment that isn't useful for me referencing a couple years down the road?
The simple best way to program is exposure, and a lot of it. Not these boring petty tasks we do. They're logic puzzles and not much else. Showing someone how everything works from start to finish in creating a website with a specified framework helps tremendously. Or how to work with low level C programming making practical applications.
For myself personally I developed a method of TODO's with some of what my lead taught me mixed in. My lead doesn't like redundant code, but said "working code is better than no code." So what I did is made one type of TODO that means "this code sucks or should very much be revised." Another one I have is "talk to my lead." With those, I don't address it with my lead unless we already have a meeting and it'll be quick, or I compound enough of them to devote an actual meeting regarding them.
Overall it has helped me stay organized, and it keeps me from annoying my lead. So what I'd add is, a system for people to make their own notetaking is vital when learning. If you don't have that or arent willing to take the initiative to do that, personally I think coding is not for you.
I love that taxonomy of TODOs, I'm stealing that ;)
> I think what a lot of instructors fail at is they don't give students a working example of how something works. Sure you're not really going to learn, but what's the point of me having a half-assed assignment that isn't useful for me referencing a couple years down the road?
Like everything else in life it's a balancing act (or a chicken and egg problem). In a university/college context in particular it's not about being practical, it's about learning the (hopefully up-to-date) theory. There are concepts, classes of problems, and mental tools in computer science that are extremely valuable, but if you don't teach them explicitly you have everyone reinventing the wheel, and worse, doing it without a common vocabulary.
But as a student you can learn/memorise some concept (let's say recursion as an example), but you never really 'get it' until you've struggled with a real-world problem and realised that recursion solves it elegantly.
Sometimes the way we teach reminds me of hypnopaedia/sleep-teaching in Brave New World:
```
A small boy, asleep on his right side, the right arm stuck out, the right hand hanging limply over the edge of the bed. Through a round grating in the side of a box a voice speaks softly.
'The Nile is the longest river in Africa and the second in the length of all rivers of the globe. Although falling short of the length...'
At breakfast the next morning, 'Tommy,' someone says, 'do you know which is the longest river in Africa?' A shaking of the head. 'But don't you remember something that begins: 'The Nile is the...'
'The-Nile-is-the-longest-river-in-Africa-and-the-second-in-length-of-all-the-rivers-of-the-globe...' The words come rushing out. 'Although-falling-short-of...'
'Well now, which is the longest river in Africa?'
The eyes are blank. 'I don't know.'
```
The takeaway (in the book at least) is that rote-learning like that has no value because its not conscious knowledge (but it's great for _moral_ lessons, like 'Ending is better than mending'). But I've lost count of the times where I've come up against a problem that niggles at the mind and realised I learned to solve it years ago at university, and it all falls into place. If nothing else, you know what to google for.
So I've come around full circle on how theory-heavy universities are (if we don't teach theory at university, where would we teach it?), but agree that there's a huge benefit to student experience by pairing it with exposure to full systems.
The older I get the more I find myself regretting (/resenting) how we've off-loaded so much job training to universities. You know how students can get exposed to real-world systems and learn real-world lessons? By having them recruited by real-world companies who invest in their development.
Seems like a CS degree would be most useful after you've been working with real-world code for ~5 years. Perhaps we need to split out most of the content of the current undergrad degrees into a CS equivalent of an MBA? Let the undergrads focus on practicality (ie, making the MIT missing semester the core experience), then come back in a few years to learn all the "correct terms" for the problems you've been coming across and learn the best-practice/optimal approaches.
If you really like TODO's, here is my personal system. I've been trying to expand it but these are the major ones. I do it in a specific way too so that they stand out and i can organize in ascending order:
TODO: --0-- This is my "talk to my lead" todo. If i can't figure something out, or i need clarification on something, i throw this on here. Sometimes I'm able to figure it out later which is why i mark these. But normally they're reserved for further clarification and I'm just going on assumptions until I need that info.
TODO: --1-- This todo is a task that needs to get done or there is something vital and I haven't implemented it or need to figure it out.
TODO: --2-- This todo is the redundant or bad code todo. It works and is like a priority 1, but only when it prevents you from completing another priority 1.
TODO: --3-- This is a "it's not great and I'd like to redo this, but it gets the job done" level. This one was for when i'd have something petty or minor that i know is maybe bad form or inefficient, but i just don't have the time to deploy and test a complex datastructure to it. So what if I have 4 nested for loops. It works and it's reliable and thats all the client needs.
TODO: --4-- This is my wishlist one. Typically I do this more for personal projects, but on occasion at work, I know theres a feature i could implement at some point that could really help out. This usually falls in the category of "if i have absolutely nothing to do." It's just a way to keep ideas somewhere.
I've started to having global todos but I haven't fleshed it out much. Typically i'd throw them at the top of a class or something stating an issue or bug. Haven't really messed with it much but my tiering system has helped tremendously.
The biggest step for me was to never touch the student keyboards. And then I basically only answered their questions with more questions.
Sometimes I would hear students grumble "He never answers my questions...", But in the long run, they would start asking themselves the same questions they knew I would ask (what did you expect it to do?, what did it do?, Why did it do that?)... Then they would usually solve their problem without me!
Or, when they called me over they would start with "I tried a, b, and c" and got results x, y, and z" which is a way better start to a learning experience for everyone than the old "it doesn't work, fix it, please"