It was only later once I was interested in web development that I started picking up linux, learning more deeply about the compilation process, learning algorithms etc. For a beginner all that stuff is just more roadblocks to building your interest and foundation. But later I started hitting a wall when trying web development or 3d game programming where I didn’t have the fundamentals and thats when I started learning all the other skills besides just typing some code and hitting the green run button. In the transition from beginner programmer to Intermediate programmer is where I would say one should learn the behind the scenes concepts not while you’re still building an interest and foundation.
Also interesting aside the programming environment I started on was called “Kids Programming Language” it was like a kind of simplified blackbox environment that I compared to flash (but didnt cost money). Even today I prefer to introduce coding in such blackbox environments like processing.js maybe because of that.
So for the simple for loop for(int i = 0; i< something; i++){} there is a large number of syntax errors a beginner can do, he can forget to open or close the () , he can forget about the : or placed them in the wrong place, he can forget about the {}.
For sure I do not start teaching my son about the c++ compiler, linker though I show him how the program runs in the IDE debugger and how changes update.
Low level stuff is needed much later for maybe parts of the students, at the beginning is too much junk that needs to be learned like a parrot.
However it's not entirely a matter of when you started to touch the keyboard. Around me I see "people who understand" and "people who use" of various ages. Guess who helps who more often.
You could, or at least the tip of that iceberg. Compiling a simple program often is a simple one-line command. Perhaps you can show him how to automate this with a shell script or (gasp) a makefile.
The reason why it is not "junk" is that it will teach him a bunch of important things: that you can "talk" to a computer using different languages, that those languages have different capabilities, different properties and different grammars (syntax), and that languages are all about grammar and semantics.
> Low level stuff [...] at the beginning is too much junk that needs to be learned like a parrot.
I see a problem with teaching there, rather than a problem with what to teach. Anytime you make people learn by heart something that needs to be understood first, there's a failure to teach.
It seems these days that we are trying to rush people who are not even comfortable with files and folders to "code". That's stupid in itself.
How about teaching them how to use a computer before trying to program it? Is it not a saner approach? Even if they don't get programming at least they'll know a bit better how those things actually work.
(And why the hell your son has to learn C++ first thing in the morning when there are more beginner-friendly languages. That's another major failure, if that's true.)
It follows the general philosophy that a computer is just a tool that should be at people's command. But that approach only makes good customers, people that are helpless when problems come. Farmers had that sort of problem and had to fight to have the right to repair their "tool".
The correct and actually beneficial philosophy is user-tool co-evolution, that is mutual adaptation. And for this to happen, the user has to really understand their tool.
>The reason why it is not "junk" is that it will teach him a bunch of important things: that you can "talk" to a computer using different languages, that those languages have different capabilities, different properties and different grammars (syntax), and that languages are all about grammar and semantics.
My point is not that he should not know about the low level stuff eventually, but keep that for the second or third year.
But int he end the reality s that we write text and some tool makes it run and print stuff on screen, is not important that everyone understands that the compiler has 3 parts/stages and that the linker searches for stuff in some weird paths using some weird algorithm... for first years of teaching I think is OK we focus on understanding the fundamentals and not the tools, we would waste our time teaching them about the c++ linker or Java classpath if they will use Python or JS in the real world.
I identified 2 hard parts
1 create the solution for the problem, like say add all numbers from 1 to n , my son can't invent the solution, I have to make with him similar problems over and over again until things connect (is the same for Math and physics, we repeat same type of problem until it makes sense and he can solve them himself)
2 the syntax, I can work with him, make some simple programs and next week he fails to use "cout" and "cin" properly , this means I failed to identify that he did not properly understand how this crap works and have to do more examples with cout and cin too.
This would be a good point if the year where 2003. Compiling code and setting up a proper coding environment is a solved problem that isn't worth the headspace of a young and aspiring programmer. In the modern day, you can open up the console on your browser and start writing and running code just like that.
What's far more important for a beginner is to learn algorithms and data structures, which are timeless concepts that are highly valued and can be applied to any language or environment (and to give OP credit, C++ is a fine language for learning these concepts). Recursion vs iteration, control flow, data structures, time-complexity -- gaining a mastery of these topics will enable the student to write programs that make it worth while to then learn the auxiliary technologies that can make their programs usable and sharable -- unix commands, compilers, linkers, etc -- learning these tools as a means to an end.
> The correct and actually beneficial philosophy is user-tool co-evolution, that is mutual adaptation. And for this to happen, the user has to really understand their tool.
I would argue that a lot of existing technologies such as unix are less so philosophy driven and more so backwards-compatibility driven where things exist purely for historic reasons. The idiosyncrasies of say unix can be a headache for a beginner, and it'd be a better use of their time to only interact with those technologies when absolutely necessary.
> Compiling code and setting up a proper coding environment is a solved problem that isn't worth the headspace of a young and aspiring programmer. In the modern day, you can open up the console on your browser and start writing and running code just like that.
Noone should get into writing more complex programs without understanding the basics of the tooling, and we at most only have a few auto-generators that will create a skeleton that can and will break with ever so slightly a change.
"Modernity" has nothing to do with it. In the old days you could switch on you family computer and start entering Basic just like that too. The only difference between yesterday and now, is that the leverage is much stronger.
Adding and multiplying matrix has been a solved problem too for an even longer time, yet we teach students how to do it manually. It's a solved problem, yet we expect them to understand the solution and be able to execute it.
I don't know why it shouldn't be the case also in CS, unless what you want is code monkeys [1]
> Recursion vs iteration
You cannot explain that properly without explaining first that compilers to stack machines, routine calls and jumps. If you skip that you just end up saying "anyway use iteration when your program mysteriously blows up". Actually if you do go all of a sudden low-level like this, your students will discard your explanation and remember the previous rule of thumb. That's one of the reasons why some people bad mouth us, saying we abuse the terms "science" and "engineering" in "computer science" and "software engineering".
CS 101 should always be in assembly language on some 8bits micro-controller. If you don't do that, you are cutting corners.
[1] https://www.joelonsoftware.com/2005/12/29/the-perils-of-java...
Isn't this a implementation detail? I mean it depends if your course is focused on teaching programming first level (how to get some simple problem then math and code it with if, for and while and some variables) or if you actually have a course about say c++ where you get in detail about why this old languages are designed how they are.
Just to make things clear, I don't like "magic", I too prefer to understand how the computer works from the logic gates up though I am still missing some stuff in my knowledge. But what I noticed is the introduction to programming is very hard, I remember me wasting hours explaining stuff to a student colleague and after those many hours he had the revelation " so this computer is dumb, we have to tell it to do everything step by step , all details..." , so you have the problem of teaching the students algorithms where for myu son they use some C-like pseudo code, then you want them to start running those algorithms ASAP so they can get feedback from the machine , but the syntax is a big issue. It would not be efficient to teach them to also use the command line(Windows and Linux), run the compiler, troubleshoot if the command fails to run(maybe wrong directory or paths), then do the parse the syntax errors and try to find the actual error that produces that sometimes unrelated message. With and IDE you might get the red squiggly lines as you type with some hints on what is missing (before you write 10 new lines and not know what is the problematic one.
But I agree with you if the student is not in the first year of learning programming and indeed the people that do computer science they will study compilers and CPu architecture, and data structures and lot of stuff.
As much as the fact that numbers are stored on a finite number of bits. Your iterative factorial won't blow up for 100! but gives an obviously wrong result, like a negative number.
Don't blame C/C++; blaming the tool is generally a bad idea (now if your school teaches cooking using flamethrowers that's a different story...). Many languages don't make promises about tail call optimization. A lot of languages don't have "big numbers" (as in Lisp) support - even "modern" ones. Very few languages will accept recursive data structure definitions without using pointers (or references if you want, but the label you put on this can of worms doesn't make much difference). Some will actually give the right-ish result because they use floating point numbers internally, but then you might have to explain why the hell 1/10 does not give exactly 0.1 (which is why, in some algorithms, you compare not-so-real numbers using <= instead of ==).
You cannot escape the fact that computers are mechanical machines, not abstract math machines (unless you load a program that does precisely that). Part of "the Art of Programming" is about overcoming that limitation.
Abstractions are lies by definition. Lies are sometimes a necessary evil, but abstraction abuse is a poison.
The only time I have ever used javac was for fun. Not once professionally.
Good education should give you understanding of the basics, not just higher-level stuff. It's easier to learn high-level stuff when you got the basics down than to unlearn the "magic black box" approach and dive into basics when you need it.
Too late for what, though? At any point in time there's a certain subset of knowledge that's most relevant that you're trying to do. If it's learning overall programming concepts not the internals of a language which you may or may not use, then NOT using the IDE automation would be detrimental.
Furthermore, in every single project that i've worked on professionally, attempting to manually manage dependencies and the way things are compiled would earn me odd looks, since that's far more tedious and less productive than just using Maven/Gradle. Not only that, but manually attempting to manage imports as opposed to letting my IDE do everything that's needed in the background would provide me precisely 0 benefit.
In my eyes, "It just works", isn't a bad thing at all, as long as you:
- can look into the lower level mechanisms (but only once actually needed)
- can find information about all of it, to make the above easier
Why would you "unlearn" something if you'll still use it in 95% of the cases, the lower level approaches being the outlier?Of course, we're not talking about doing javac manually when you're working, we're talking about learning the basics before going on to use the automation. BTW Maven and Gradle have plenty of gotchas of their own. If you don't understand what exactly happens you won't solve "magical" problems like old builds of non-snapshot versions remaining in the repo for example.
> manually attempting to manage imports as opposed to letting my IDE do everything that's needed in the background would provide me precisely 0 benefit.
you say that, and just last month I've had to help a guy manually remove an import of Token class from a wrong package that "magically broke his code" :)
> Why would you "unlearn" something if you'll still use it in 95% of the cases, the lower level approaches being the outlier?
Because I've seen a lot of people decide something that always worked is not their responsibility to fix when it doesn't work. That's how you end up with 1 guy in the company that understands the build system :)
Hmm, the IDE should offer you multiple classes to import from in a dropdown if there's any ambiguity, as well as highlight any of the methods that aren't present or whose signatures differ and provide popups with essentially the same information that you'd get from the compiler, without even having to compile the project. In that regard, i'd say that IDEs are actually superior. A single ctrl+click that'd take you to the source of the class that you've imported should also clear up any confusion about the import.
Importing the wrong thing and not bothering to figure out why their code doesn't work honestly feels like not being familiar with the language itself (as opposed to the tooling) and for some reason not trying to figure it out on their own by reading what the IDE is telling them - to me, that does sound more like learnt helplessness than anything else, which would also manifest itself when writing code and running into design patterns that they don't understand, as well as any number of other situations.
> Because I've seen a lot of people decide something that always worked is not their responsibility to fix when it doesn't work. That's how you end up with 1 guy in the company that understands the build system :)
To me, this also feels like more of an organizational issue: if companies don't have a RACI matrix (https://en.wikipedia.org/wiki/Responsibility_assignment_matr...) and have a low bus factor (https://en.wikipedia.org/wiki/Bus_factor), then that's on them. If no one takes initiative and the company fails to find employees who will, that's also on them. If only one person understands how things work and doesn't document it, nor are there processes in place to ensure any sort of knowledge transfer, then that's also on them.
That does sound like a dysfunctional environment and at that point builds will be the least of your worries - figuring out how to get code to prod, how to work with the DB and run tests (if any are present), as well as any other steps that haven't been formalized with an "Infrastructure as Code" approach will cause far worse problems down the road. Good luck if any of your servers ever go down and you haven't used something like Ansible for configuring them, but instead it was done N years ago by someone who's long gone along with their knowledge about how to do that.
If you work in such an environment and care about personal success, consider either changing the company or changing companies.
This has not been my experience, at least with IntelliJ in the context of Java projects. Bad imports result in IDE highlighting the erroneous usages of the imported class, by showing which methods aren't available. The red squiggles provide immediate feedback and let you know whether any problem lies within the method parameters, or whether the method itself isn't found, before you try to compile/run anything manually. Tooltips about the error contents are also pretty useful, no need to manually go to the file/line based on some text output in a terminal.
Bad language targets/JDK choices are far "louder" as far as the amount of errors output go, but they're easy to figure out, since if you ignore everything being red in the IDE and instead try to compile the project, you'll get the exact same output that the compiler will generate. It's just a matter of Googling those errors, regardless of how you compile your projects.
The only problems of such sort that i've run into have all been because of the Spring framework and its configuration mappings not being detected properly because some developer decided to initialize it in a non-standard way which confuses the IDE. Then again, using a code editor instead of an IDE wouldn't really provide any useful functionality/hints for Spring either, so i guess that ended up being roughly equivalent.
Sure you can play Google whackamole but a lot of times the compiler message alone isn't going to help you and when you Google the message you there are 20 questions on SO where the top answer has 1000 votes and says something like, delete the bin folder and restart.
But that's not the issue. The issue is your importing two projects that are targeting different dotnet frameworks.
The dependency project builds fine on its own.
They project using the dependency just loudly proclaims that the imported type doesn't exist.
Rider gives you a few squiggly lines and tells you "Computer says no"
You yourself have to figure out that one of the projects has changed targeting framework while the other one hasn't
To be fair they have 30 files open in the IDE and 100 lines are highlighted cause of spelling errors, it's easy to miss the line highlighted in red as opposed to yellow or black. If you look at the console output you will know the reason build failed immediately, but that's hidden behind 5 different things begging for your attention.
It is learned helplessness, but there's a reason people learn it - they went straight for the industrial tools with dozens of variables that were never explained. They never learnt how it works under the hood and what all the knobs do. They were taught to follow the tutorial, ignore the warnings, leave the defaults as is and click the big green triangle to run the program. 99% of the time it works and when it doesn't maybe start from the beginning again and follow the tutorial more carefully :)
It's a generalization of course, there are people who problem solve better and worse in any demographic, but in my opinion the tendency is - depending on tools and automation early in your education makes you a worse problem-solver.
> If no one takes initiative and the company fails to find employees who will, that's also on them. If only one person understands how things work and doesn't document it, nor are there processes in place to ensure any sort of knowledge transfer, then that's also on them.
There's organizational goals and processes, and there's company culture. The latter is far more important in practice. And it's mostly shaped by the attitudes and expectations of people, not by putting a document on company's wiki or talking about it in a meeting.
Then why not address those things first? Most IDEs should allow you to set up inspection profiles or customize the spellchecker and version this configuration so all developers would get a consistent and noise free experience, just like you should be doing anyways when not using an IDE but instead using a code editor together with a linter/formatter and Git hooks.
JetBrains products are actually pretty good in that regard, personally i've sometimes enabled almost all of the warnings, apart from some of the conflicting ones, just to learn about more concerns that i would have otherwise not thought about myself. Not that most people should do in their everyday lives when they want to get things done, but being able to do so is nice.
> They were taught to follow the tutorial, ignore the warnings, leave the defaults as is and click the big green triangle to run the program.
That sounds like that joke about everyone ignoring 99 warnings within their project because the code compiles and runs. Once again, i do believe that this is a bit orthogonal to the IDE vs code editor debate, because if there are warnings within your project you should address them regardless of the tools that you use. If it's a bad tutorial, then why are you using it?
Of course, one can also talk about how defaults should be sensible and the default configurations/examples should never have warnings, but i guess that's just what you get when people don't pay attention to the quality of the things that they make, which is at the very least understandable in our current world.
> It's a generalization of course, there are people who problem solve better and worse in any demographic, but in my opinion the tendency is - depending on tools and automation early in your education makes you a worse problem-solver.
This is an interesting argument. I don't necessarily agree that the automation is the cause for this, merely a canary of sorts. Perhaps the people who don't have the patience to struggle with the "traditional/old" way of doing things would simply not stick around in the industry for long (this probably applies to situations where they'd have to write ASM instead of Python, as an example) due to the frustration they'd experience with all of it and not getting any demonstrable results early on, which is extremely discouraging, as opposed to the more patient and persistent people? In that regard, IDEs indeed enable a wider variety of people to stay within the industry.
I cannot comment on whether that's a bad thing or a good thing, much like some people said that we'd not always have calculators with us and yet almost everyone does have a smartphone in their pocket.
> There's organizational goals and processes, and there's company culture. The latter is far more important in practice. And it's mostly shaped by the attitudes and expectations of people, not by putting a document on company's wiki or talking about it in a meeting.
This is debatable. Those two are not mutually exclusive. Look for environments where both live up to your standards and contribute to both in a positive way.
I certainly have, for example, in one of our projects now all of the configuration lives in Git and is managed through Ansible, so we know when, why and who changed things. I've also made running services more consistent, have containerized apps to get rid of the dependency hell and have written plenty of scripts for automating the bits where people made mistakes, e.g. long DB migration names that need a particular format like V20211107.5.4.2.21.1.0_Alter_Some_Table_Do_Something
At the same time i've also onboarded new people, helped them get started and have explained things both about the projects as well as things in the industry in general, as well have pointed them towards useful learning resources. Being pleasant to work with and having a healthy environment doesn't need to come at the expense of anything else, apart from maybe people's egos sometimes (including mine).
Of course, no one wants to do things for just putting a checkbox in some corporate form, but in practice most of the meaningful ways to minimize risks and make people's lives easier down the line are worth it and there are no excuses not to implement them in any mature company. That's why having documentation and enforcing that it's present is a good idea, especially if you do IaC and most of it is actually code, that's commented as well as the rest of your codebase should be.
There's not much point in teaching specific things, because there are thousands of specific things that make a program work. Yesterday my code failed because the whitelist at the server was checking my ipv6 address instead of the ipv4 on the website interface. The day before I was stumped on a Rust borrow checker thing.
You end up learning the things that you run into. If you've never needed compiler flags, it's actually not that easy to learn without a motivation. Same goes with memory barriers, garbage collection, and so on.
There's just so many rabbit holes. Telling people they need to know this or that is futile, what they need to know is how to figure out whatever their issue is. Some common tools with some common comments about pros and cons, warnings about where the caves are and what's more trivial than it looks.
My wife is starting a CS degree, and I'll be looking over her shoulder providing this kind of advice, rather than recommending anything in particular.
And you know what happens when people use a black box and that stops working? They start learning how it works then. When it has actually any relevance for them. Until then it's just a more complicated way of doing things that doesn't benefit them in any way whatsoever.
No, they don't. Because they don't even know where to start. They never learned anything outside of the compile button and the project settings.
I know because I was in that boat once. Nothing ever boosted my programming skills more than learning the basics or another layer of what's actually going on behind the abstractions.
You also need to consider hardware. School computers are not very good in general. The one I had to use for Eclipse took at least 2 minutes to start the IDE until it reached the point it actually reacted to mouse clicks. You can guess how fun the rest was. But I didn't even consider using a lightweight tool back then. Why? Because the only editor I knew was Notepad, and nobody would use that voluntarily. And nobody taught something other than fat IDEs. There was a time I'd programmed for over a year and could not code in languages like C because the program didn't have a Compile button. It was confusing and I gave up.
You underestimate how bad an IDE-only approach to teaching programming is. It comes with batteries but also learned helplessness included.
This is fixable though, instead of just telling them to use the tools you can teach students how to use them well. It also doesn't hurt to inculcate a mindset that shows them how to look for help when they are stuck. Discarding the IDE entirely is like throwing the baby out with the bathwater in my opinion.
> instead of just telling them to use the tools you can teach students how to use them well
Yes, that would be great. If only I'd ever met a teacher able and motivated enough to do that. Coincidentally, it's easier to teach about how to run a couple CLI commands and read the documentation than explaining a behemoth including everything from version control to debuggers that's all thrown in your face at once.
Hmm, what would the lesson look like? I doubt there is a way to teach everything about out-of-IDE/advanced Java development in just a single hour or two. You mentioned CLASSPATH, but there are also JARs with manifest files, there are multitude of build systems with their own configuration languages/plugins/conventions, there are ClassLoaders, there are Java Compiler Plugins... Just too much.
You either list terms for two hours straight without any details and exercises or you choose some semi-random subset of topics, which may very well not include CLASSPATH for some reason. Alternatively, you teach for ten hours instead of two.
This part stays intact either way though. You're not wrong that teaching students to run a couple of CLI commands is easier, but they still need to understand what they're doing, otherwise it can be just about as opaque as clicking a button in a graphical program.
Considering the vast majority of them will be using IDEs if they are coding in Java professionally, personally I feel it is worth taking some extra time to at least give them a starting-off point and then letting them access the documentation that the IDEs themselves provide. Whether this comes after teaching them the basics of the language through the barebones text editor + CLI tools approach or is what they are taught from the ground up is a matter of choice.
I'm confused. Where did I describe doing something as example of not being able to do it? Maybe I worded something wrong. My point was just that I was completely lost and confused in many areas for years until I went out of my way to learn things properly, despite everyone teaching me to not do it like that.
"No, they don't. Because they don't even know where to start. They never learned anything outside of the compile button and the project settings. I know because I was in that boat once."
The original statement was that people can learn about lower-level details when stuff breaks. You quoted this statement, and then add the claim they can't learn [when stuff breaks], "because they don't even know where to start". You support that by adding personal experience: "I know because I was in that boat once".
However, for other people in that proverbial boat, it seems to me that they can do the same thing that you apparently did, which is to learn what they need to know - something you deny is possible: "no, they don't."
Also, since we are quibbling about text interpretation, I'm fairly confident that nobody is _teaching_ you not to use a non-IDE approach to development. Maybe they are advising it (on the basis of IDEs being more approachable to a student) or demanding it (on the basis of an entire team working with the same tools), but _teaching_? I don't think that's right.
That ship sailed long ago. There’s honestly no need for majority of programmers these days to go cli, vim/emacs way or whatever the one true way is these days. It’s just not needed.
And the ones who need it for their work they learn it, know it, and do it.
Or for the fun and satisfaction of maintaining, running, and keep oiling something antique and/or analogue.
Cross the bridge when you get there.
Jokes aside, it’s a decent part of my day job and never faced any problem. Neither do my younger colleagues who never ever were even exposed to those esoteric programming thingies.
The problem is the belief that cli or mildly esoteric CS practises and skills have to be some kind of mandatory initiation.
I never did CS classes (I taught a couple once).
I agree that you don't need to learn CLI in the first year.
The idea that the majority of "programmers" can tackle production code without ever being introduced to a CLI is terrifying, though. I'm astonished to learn that some people think you can get a Computer Science degree without learning processor architecture, IO, operating systems and so on.
FWIW, I hate git. It's the devil to learn, and it solves a load of problems I've never had. I wouldn't inflict it on a first-year student.
Of course you need to know what a file is to use git; but you need to know what a file is to use any VCS. I don't see how you can teach someone programming before they know what a file is.
Is a CS course now little more than a way to get an introductory programming qualification?
What is `SyntaxError: invalid syntax` for `print(hello world)`? What is `NameError: name 'Print' is not defined`? I don't have any names, I just want to show a string.
The only differences are: a) amount of new things to learn (e.g. students already know how to use GUI, but learning CLI is a whole separate skill); b) quality of the tool (e.g. how relevant/readable error messages and configuration are); c) your ability to get help with the specific tool you're using.
You have to stop digging into details somewhere. You can always go deeper, if you want.
In my opinion, it's perfectly reasonable to learn one thing at a time. You can start with learning CLI and then learn Java using javac. You can also start with learning some IDE and its build facilities and use Java completely inside it.
Figuring out compilation errors when using the configuration of the IDE versus using known system environment variable that are using different values. Notably the resolution of classpaths.
The fact you are asking about it, is scary.
I've programmed java professionally for 6+ years, never had to deal with that.
Talking about implicitly learning from your IDE is a lot like learning to program with React versus the browser console (or a sandbox). I'm not sure how 'purism' applies.
I don't think there's any difference between using javac and using an IDE. They're both tools that you configure and the press a button to run. What's the difference?
And the danger with saying 'you should understand it at the lower level' is anyone can challenge you if you understand the tools you use at a lower level, and at some point you won't, because nobody understands it all, and then they can point and laugh at you like you're pointing and laughing at others.
But I do most of my work in Visual Studio, which I prefer over vim+make+gdb because a powerful IDE does give you a significant advantage over a 'mere' text editor. I also find that working in vim imposes a much higher mental load than doing the same in MSVC (and don't get me started on vi without the 'm'...).
The whole reason computers work at all is because of the many many layers of abstraction. At some point everything seems like a mystical black box to you too.
Sure it might be at a lower level. But there's always a point where you get to "I just do this and it does what it says it should. I don't understand how it works." Do you feel like a terrible thing has been inflicted on you because you don't know how the Linux kernel works internally, or how `idiv` is implemented, or which SRAM cells your CPU uses?
You have to stop somewhere, and running javac manually is something almost no Java developers do so learning it definitely seems like a terrible thing to inflict on beginners.
Yeah we’ve all heard that one before