I suspect that many of us didn't initially learn programming from a class, but picked it up on our own. What are some bad habits you picked up from your first language?
I started programming in BASIC (MICROSOFT BASIC 1.0) on a Dragon 32, and it was really easy to spaghetti code (ON x GOTO, GOSUB...).
I will never forget my Computer Science professor in the first year at University humoring the endless chase of goto in BASIC code on the blackboard, it hurt a bit thinking I've done that ;)
Now more than 25 years have passed, I hope I put that behind me definately... :)
My first language was JavaScript (unless you want to count HTML...). It was great to learn because it's such a forgiving language, but it also set me up for some really bad habits that still trip me up occasionally.
In particular, the fact that JS doesn't require a semi-colon to terminate each line. I still frequently have to go back and add semi-colons to my PHP code after making a small change...
Another biggie, compounded by the fact that PHP shares this "feature," is weak typing. Oh, how I wish C# would just know to call the damn .toString() automatically when I'm spitting out some label or message...
My first language was Sinclair Basic (on the 1K ZX81). A few highlights of the language included:
You had to use line numbers, which meant program flow inevitably revolved around the dreaded GOTO statement. It took me a while to grasp how a programming language without line numbers could work!
String variable names could only be 1 character long. That's right, one alphabetical character. But as RAM was limited to 1K, you couldn't afford to use longer names anyway. Hence variables always tended to be X, Y, A, B, C etc.
Again, because of limited RAM, the main thing you learnt was that readability was of secondary importance to terseness - the less characters you used, the better.
See this beautiful ZX81 manual.
Well, technically my first programming language was TI-BASIC on the TI-83 calculator. We had flow control, but it felt rather inconvenient, because for a long time I didn't know how to have multi-line if
statements. So goto
it was. It didn't use line numbers, but it did only allow two-letter label
s, so I had to cram as much meaning as I could into two letters to keep track of what label
did what. But that's not the kicker:
For variables, we could only use a single letter, or we could make a list, but it could only have a short name (which could never really describe all the elements I stuffed into it), or we could make a matrix, which was even more confusing. All of those could only be numbers. If we wanted string data, we had a few string variables, but no real way to manipulate them. Now, obviously the simple variables only had 26 values (A-Z), but we did have an unlimited number of lists. But for matricies we only had A-J (or so - I can't remember), and for strings we only had 10 of them. And you couldn't add more.
But the real problem with all of this was that all three of these kinds of variables were completely global - I could run a program, and if that program used the variable A
in it, I could see the value of A
when the program was done. And if you weren't careful, that value of A
could muck up your program the next time you run it!
We didn't even have files, so I can only miss the lack of any file I/O in retrospect.
My first real programming language was Visual Basic 3.0. Sometimes, when I'm creating controls on an ASP.NET page, I default to Hungarian notation for the controls, e.g., btnSubmit
or txtUserName
.
BASIC on the C64.
bad habits? none, except that it took me some time to learn something different, not due to lack of skills, just because of lack of an alternative environment (I had an Amiga 500, then Amiga 1200, and I was not able to find compilers for them. Internet was not yet an option at that time)
It took me a while to stop using strcpy
and char myString[256]
in C++ instead of the std::string
class.
On the goto riff, I'd have to say my first language (Visual Basic) error handling gave me a
On Error Goto LineLabel
view that gives me bad habits when I do exception handling.
Hungarian-esque notation from Javascript.
Because it's all duck-typing in JS and there isn't anything like a Visual Studio to help you inspect and refactor, it encourages you to name your variables according to their intended use - I still think this is one of the few valid use-cases for sys-Hungarian.
Prefixing objects instances with "o" is still a curse I slip into with C# (and hastily correct) from time to time.
I learned Hungarian Notation from VB3. It stuck with me for years, and finally about four years ago I kicked the habit.
Not my first language by far... but when I'm working in C#, I still occasionally catch myself writing:
int someArray[];
instead of
int[] someArray;
Not very impressive as bad habits go, but I think I've gotten rid of just about all the real bad habits by now.
Similarly, I sometimes forget the new
keyword and wonder why intellisense isn't working for my constructor.
Everything gets a class (from Java).
Took a while to realize how to structure things nicely.
I wouldn't call it a disadvantage, more of a stumbling block, but learning procedural programming using Basic and Pascal originally made the transition to object-oriented programming waaaay harder. It meant an initial period of writing procedural programs in an OO language like Java...
The worst things I did in my first language, which was Apple Integer BASIC, were using GOTOs and global variables. I can't call using GOTOs a bad habit with me because I was ready to be rid of them by the time I had access to a language which provided an alternative, which was Apple Pascal. However, it took me some time to figure out how to write a program with minimal use of global variables, so I would say the over use of globals qualified as a bad habit.
The only really bad habit I got from BASIC that had to be unlearned later was an excessive dependence on global variables. At the time they just seemed so much easier than dealing with scoping.
I did learn a lot more bad habits from BASIC, but I also learned from sad experience why they were bad, and not to do them.
Good examples would be: goto-ghetti, when to and not to use subroutines, and the importance of planning ahead.
Oh, and the importance of off-site backups:
My parents used to think it was funny to send my baby sister into my room to wake me up on Saturday mornings. One day after failing she instead got hold of one of my tapes (TRS-80's initially used cassette tapes instead of floppies or hard-drives), stuck her finger inside, and started to gleefully pull out yards and yards of the magnetic tape. That tape contained all the personal BASIC programming projects I'd been working on for the last year. Suffice it to say that in short order actions were taken that made everyone in the family mad at everyone else. It did work to wake me up though...
I don't know if I learned really bad habits from QBASIC. I worked out structured programming on my own, as well as the needed memory structures for argument passing. I hadn't learned how to use subs, so everything was IF...GOTO. My code was very structured by the time I moved on to C++; it just didn't use very advanced concepts. :-)
Mixing things up in the same function.
The language was BASIC, and it didn't have functions. I did "functions" with gosub
. I would gosub
to line 10000 or 20000 and write the "function" there. Since this was a pain in the ass, for small stuff I didn't actually make the gosub
.
I lost the habit a while ago. Now I get nervous when a function serves more than one purpose.
Mutable state.
EDIT: Let's elaborate some... Most of the mainstream languages default to mutability. They encourage a programming style that promotes side-effects, which makes it hard to reason about the program and makes writing concurrent programs hard (because of the need for locking). In many cases it's possible to write better programs through a more functional approach, where things default to immutability and no side-effects. If you anyways need to use an object oriented or procedural language, knowing functional programming lets you write better programs in those languages, even if they do not support functional programming natively.
My first language was C, was obsessed with pointers. Used it for everything.
Moving to C++, pointers produced some pretty weird results in objects.
In C# I miss them.
Constantly complaining about how this task could have been so much easier in my first language.
(Python)
- bad indentation
- non consistent function, class, and variable names
- debatable: not declaring types
Not tidying up after myself. Actually this is a recent bad habit for me with more and more garbage-collected languages. Got bitten recently because some COM objects weren't being garbage collected when my process had finished. Wouldn't have been a problem if I'd released them myself.
Really poor exception handling practices. Exception handling is so important and I never did grasp that in the early days.
Many things:
- Soda addiction
- Bad vision
- Insomnia
- Wrist pain
- Difficulty converting to OOP
- Difficulty thinking in OOP
- Writing good and efficient algorithms that people in OOP dislike
- Thinking in procedural programming
- Listening to heavy metal while coding
- Arguing with myself
- Talking to myself in code
- Thinking that everything in nature can be proven by code
...(the list goes on)
I wish I had to handle memory management myself in Turbo Basic, where I first started as a kid. This way I could have learned C sooner.
Plus, I would be much more grateful for the wonders of garbage collection when I first met it.
For a long time I named all my interfaces IFoo and IBlah, thanks to a long time spent with COM.
My first programming language was Microsoft's COMMODORE BASIC V2. Line numbers, GOTO statements, variables limited to 2 character names, abysmally slow ... it was all around pretty awful. So the one thing it taught me was "ignore what they gave you, and find a better way". I taught myself 6502 assembly from the hardware reference manual. It was more flexible and orders of magnitude faster, and to do anything fun on the C=64 you needed a million PEEK/POKE statements so it wasn't actually much worse in terms of readability anyway.
When I went to college, they were teaching C++ and (later) Java. It made me want to poke my eyes out, so I taught myself Lisp for fun. And boy did that get me in trouble: once you know Lisp, it's really hard to get yourself to want to write Java for some class. (Hey, what's REDUCE in Java 1.1? ...you're shitting me.) I survived Data Structures by doing my homework first in Lisp (so I could understand it), and then porting to Java (which was required). I have no idea how anybody else learned computer science, writing in a language like Java: it was so painfully verbose the important ideas were all hidden.
Is that a bad habit? I still don't know. These days when I've interviewed, I write Lisp in interviews (or maybe as low-level as Python or Ruby). Curiously, the companies I want to work for don't care if I know Java, but they love that I taught myself Lisp and assembly. And even when I have to write lower-level code, like C#, it looks a lot more like 1996 Lisp than 1996 Java.
Not so much my first language, as my first programming environment -- writing FORTRAN
at a teletype has left me with the bad habit of pounding hard on the keyboard.
I started with FutureBASIC back in 1995 or so. Everything was hard-coded (recursion escaped me completely until about the past year or so), I didn't know how to draw from other source files, and I didn't see the difference between FN userFunction
and GOSUB
, so I did GOSUB
for everything.