The Need to Grind Concrete Examples Before Jumping Up a Level of Abstraction
justinmath.com
justinmath.com
I feel that's more a lesson for a lot of math teachers to understand. I remember some frustrating linear algebra, calculus and computational complexity courses where the lector basically threw some formulas onto the blackboard, went line-by-line through a formal proof of their correctness and then called it a day. Giving actual examples of the application of the formula was an afterthought left to the student aides. Giving examples that could explain the derivation of the formula was not even considered as an idea.
It always reminded me of someone teaching an "introduction to vi" course but then just scrolling through vi's source code without any further explanation - and in the end expecting the students to be able to fluently use vi.
It's one thing to take two float arrays, multiply them componentwise and sum the results. It's another thing to understand why this operation constitutes the dot product in R^n vector spaces.
Then there is the fun part in German that the dot product and inner product are both called Skalarprodukt. There are many inner products of which the dot product is only one.
> I feel that's more a lesson for a lot of math teachers to understand.
That's certainly true, but the teachers who teach that way were probably once students who tried to learn that way (I was one on both counts, though I got better), and it'll be better for them as teachers if they learn the lesson as students.
The professor is in an awkward position, because the professor at the front of of the large-group lecture hall doesn't have anything to do to add value. Watch videos, read book, work exercise, and then go to recitation or office hourse for interactive tutoring.
A common sign of prematurely deduplicated code is a common function with lots of boolean flags and other knobs to tweak its behaviour for every use case added after it was written.
Students learning DRY on day 1 and then applying it to the max before intuitively understanding the problems DRY solves.
I encounter people trying to establish standards and abstract patterns on the first pass of code...
I put, for instance, TDD in the drills category. I don’t think you should live in TDD. nor do I think you should avoid TDD because someone said they thought it wasn’t a viable lifestyle choice. You should do it for a while every six months or a year to knock the cobwebs off and remind you what sort of tests you’re going to need and write code that complements good tests, rather than fighting them.
DRY is a bit more complex. I think DRY in unit and integration tests is a slow death. Tests should be DAMP because requirements change, and so do languages, frameworks and libraries. DAMP avoids the sunk cost fallacy which I’ve seen nerd snipe too many people. Test isn’t useful anymore? Just delete it. Or replace it. Boom, done.
The military also. Individuals learn 'part task' drills (e.g. firing a tank gun), then practice them in a team environment (e.g. the different crew roles working together in a single tank) and then finally (in something fairly unique to the military) exercising collectively: multiple teams working together to achieve a common task. E.g. several tanks coordinating an attack, then adding in infantry, etc.
Brought to mind "wax on, wax off" from the original Karate Kid movie.
DAMP... Do Always More Pasting
Descriptive And Meaningful Prose
Just have your test say what it does. Don’t play code gold and get clever. Tests for different features should be able to die separately. No coupling.
a concrete problem domain has an ideal solution with ideal abstractions for its purposes
seek to understand your problem domain to a reasonable extent before writing hard-to-change code
Of course, we don't understand the problem domain perfectly from the start, and neither do we write perfect programs from the start. It's an iterative process of optimization, where you alternatively work on a specific understanding or work on the understanding. Everyone has to figure out that balance for themselves.That's precisely why it's useful.
"On your discretion" would just lead to endless bikeshedding - as having a useful discretion requires that you are already advanced enough to not need such advice.
It's not that new devs really understand three to be some special number either: just a useful heuristic, which can be 2 or 4 or 5 if needed.
Suppose you started from first principles and navigated down the ontology tree taking one of the shortest paths (well, shortest-ish since it's a hard problem that'll burn up too much time otherwise.) Would you encounter your deduplicated function on the way? If not, it's making it worse.
One issue I have with math problems is that sometimes I wish I could immediately go down one level of abstraction and see something like a physics or programming problem that applies that specific or related problem I'm working on. I haven't found a resource like this yet.
https://rosettacode.org/wiki/Rosetta_Code
Not a guide, per se, but it has many implementations of a wide variety of math and programming concepts, implemented in a large number of different programming languages.
Although I bet that ChatGPT might already know a lot of this kind of thing. I haven't had the chance to use LLMs in this specific context yet.
And why is it so hard to have math education based on good concrete contextualized examples, vs just rules and problem sets? Understanding the “why” behind the math is often lacking… and math doesn’t always need to be applied, that’s ok— but if it can be, it is so much easier to understand
So, now instead of one concept you have two unfamiliar concepts--one of which is far removed from your pedagogy.
It sucks, but there just aren't that many straightforward applications of abstract math classes.
Knowing whether a particular aspect of math has real application is relevant to students. And this remains hard.
[0]: https://byorgey.wordpress.com/2009/01/12/abstraction-intuiti...
a_0 + a_1 + ... + a_n
is easier to understand than the shorter sum(i = 0 to n) a_i
.But on the other hand, 2 or 3 elements of the sum are usually enough, i.e. you probably wouldn't improve understanding by writing out the first 10 elements or so.
You need:
sum(i = 0 to n) *f*(i)
and you'd like: Example: f(0) = *a_0*, f(1) = *a_1*, f(2) = *a_2*
where the stuff in *italics* is given as a concrete substitution.[0] https://news.stanford.edu/stories/2019/09/embrace-struggle-e...
That's not to say there isn't anything worthwhile in the article, but figured people would want that context.
Don't underestimate the value of time spent grinding the low levels for code that is fundamentally important to what you are doing. You come away with a much stronger understanding than if you just hack a solution, cargo culting some existing code and just shipping it.
Which of course the author always does and so they don’t get what they’ve done to people.
As noted by others this preference influences how one learns code effectively too. It's a pretty basic trait.
The author's stated preference is most common but it is not the only one.
"They say you have to use concrete examples, but not everyone needs that."
'Can you give a concrete example of that?'
Consider addition...
"We're going to learn addition today"
One approach: "it is combining two quantities into one. For example, 1 + 1 = 2, 2 + 2 = 4"
Another: "1 + 1 = 2, 2 + 2 = 4, you see, we are combining the quantities"
For some of us, getting the abstraction first gives us the mental framing that allows the examples to teach us the most and the alternative feels like noise.
For others, they're not sure what we're going on about until we have given them enough examples so that they can understand the abstraction. They want to generalize off of the examples they've seen.
Neither is inherently right but they have trade offs and we have preferences on this dimension that end up being strong and usually outside of our awareness. Frequently it can not matter if we jump back and forth between concreteness and abstraction.
I agree about the shift in university. I really enjoyed what felt like a removal of the noise. Of course, the interconnection of the pieces and learning to instantiate the concepts into concrete are expected work of students. That all said, abstraction (or models) are lossy compressions and noticing their failures is essential to avoid becoming detached and/or delusional.
Similarly I'm not sure there's a lot of understanding to be gained from writing down cosets (as in the actual list of set members). It's still necessary to know how to calculate, but the understanding of what you're trying to do comes from the fundamental theorem on homomorphisms/first isomorphism theorem. You'll never get it from looking at cosets, and in some way it's actually a bit of a distraction IMO. They're often kind of just there to prove quotients exist.
Tensor products feel similar I think: actually constructing the tensor product is not terribly interesting and mostly just demonstrates that it exists. Focusing on the concrete definition makes it easy to miss the forest for the trees.
Maybe having given a couple examples, we can extend it to the abstract idea that universal properties are usually more interesting than the associated concrete constructions. :-)
For example:
I'm thinking of a *number* between 1 and 10, for example, 3 or 7.
Is 1 allowed? Is 10 allowed? non-integers? Irrationals?A definition and theorems can seem trivial, if you latch onto the first trivial example and treat it as the canonical situation. This is very common difficulty when learning intro abstract math.
Would anyone need examples if they understand the abstraction? They can stamp out their own examples, can't they?
Needing examples after you've a grasp at the abstraction would be like saying 'I need help coming down this zip line', where as discovering or arriving at the abstraction is the result of working through and distilling n number of examples. To relate to the analogy, that's like climbing the hill in the first place.
That said, in sloppy engineering we often see the reverse. 'Here's a meta-model I cooked up overnight. Now if you spend the next 3 years gathering all the domain knowledge and expressing it in my nifty notation, you can have the outline of a potential candidate for your question. I'll write up a journal paper tomorrow about how I solved your problem'. There was a lot of that around when I was in academia.
As someone with an amateur's interest in history, I suspect that it's useless in the same way that learning words from a dictionary, or memorising multiplication tables, is useless. Learning words from a dictionary gives you no facility with a language, but you can't build much facility with a language if you don't know its words. Similarly, multiplication tables are useless for doing mathematics, but I think that it is good, both for the practice of math and in the real world, to have some basic number sense. (This is perhaps more contentious. My opinion is certainly shaped by the fact that I was among probably one of the last generations to be taught this skill, and am glad that I have it, but don't really know what it's like to grow up in a world where the skill is regarded as completely irrelevant.)
That's not to say that history classes don't lean too much on the names-and-dates approach. After all, it's easier for the teacher, both for preparing lessons and for evaluations—it's a lot easier to decide unambiguously whether a student has a date correct than if, say, that student has correctly understood the historical significance of some important event.
Don't know how I finished my CS degree, because most of the theory I just understood years after leaving university and doing some hands on work...