I'm a new programmer in college and was wondering if there are any bad habits to watch out for early on. Anything that you wish you knew to avoid when starting.
Copy and paste programming [1] is probably one of the worst habits that one can develop while starting to learn programming. Learning how to program is best achieved by writing code and understanding other people's code. If you copy/paste code without understanding what's going on, you are doing yourself more harm than good.
[1] http://en.wikipedia.org/wiki/Copy%5Fand%5Fpaste%5FprogrammingI start far too many hobby projects, and seldom manage to complete any one -- or even reach an intermediate milestone.
Not using source control.
There are a few instances where it is feasable to skip the source control. If you can count the number of characters in the source file on one hand, It's probably ok to skip the source control. Otherwise, you need it.
Using poorly named variables.
A mistake programmers often make at the beginning, is to try to write the Whole Program, then compile it and run it. They will be bombarded with 100 compile errors, and even when compiled their program probably won't do the right thing.
The way beginners should start a project, is to make a small part of the program, compile and test it, and once it is working, move on to write the next part. Continuously re-running and testing your application, while you add or change only small pieces of code, is a great way to isolate any new problems in the recently changed code.
I rewrite code I didn't write.
Don't optimise prematurely.
Donald Knuth made the following statement on optimization [1]: "We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil."
[1] http://en.wikipedia.org/wiki/Optimization%5F%28computer%5Fscience%29Not handling errors. Failing to check return codes, assert conditions or swallowing exceptions. Even in cases where it's "impossible", or "no one will ever use it again".
Spending too much time on StackOverflow instead of actually developing!
Not writing unit tests.
Not adhering to YAGNI is a big mistake. (YAGNI = you ain't gonna need it). Build what you need, not what you think you might need.
It helps when retaining a focus on the important things and the bigger picture.
Even at an API level, the intent of some functionality can be obfuscated by having multiple redundant additional methods or method overloads. Noise in a code base is annoying to work with. E.g. if you only need to load something in memory, don't provide an overload to load it from a file path "just because" you might need it in future.
This is especially the case when it comes to bugs. Unit testing finds a lot of bugs, but some will lay hidden until the functionality is actually used by someone. If you have code that is not being run, the bugs won't get found so quickly. Furthermore, when the bugs are discovered, that code might be ancient and the person who wrote it may not remember it, let alone be at the company any more.
I'm much too easily sidetracked. I want to write a program in Clojure, but first I'm going to create a Web site where the Cheat Sheet and API reference are cross-linked and extensible. But before I do that, I want to write a proxy so I can hear last.fm while I code yet another diversion...
try {
myCodeHere();
doSomethingElse();
} catch (Exception e) {
// TODO: Handle this intelligently later.
}
If I'm having a good day I might add e.printStackTrace();
.
throw ex
. It's still incomplete TODO code, but at least it's correct code. - Loadmaster
throw
; otherwise you lose your original stack trace. - ildjarn
learn these by heart so you know when you are repeating them http://en.wikipedia.org/wiki/Anti-pattern
Writing monolithic routines is one of the worst things you can do.
Try to write small, dumb code. Its harder to write code that looks like something anyone could write - that takes real skill.
It's always easy to be wary of anything that's Not Invented Here.
I think Rands summed this up best [1]:
[1] http://www.randsinrepose.com/glossary%5Frecent.html#nihNIH ("Not Invented Here")
Term to describe behavior where an engineering team will not consider working with anyone's code except their own. It's not that the external code is good or bad, it's just foreign which means it must be reviewed, reformatted... oh, what the hell. LET'S REWRITE THE WHOLE DAMNED THING. Billions of dollars have been lost to NIH. I mean it. Billions.
Definitely the lack of comments.
Also, I often find myself afraid of using "ugly" solutions, preventing me from getting work done. Of course, in itself, this isn't a bad thing, but somethings you just have to do something to keep on moving with the project.
x++; //add one to x
- Russell
Don't get hooked on just one programming language, learn what that language is good for and what its not. Learn to use the right tool for the job.
I have a tendency to forge ahead with a poorly thought out implementation when a deadline approaches telling myself I'll go back and refactor... which, of course never, happens.
try {
...
}
catch( Exception ex ) { }
Being anal and formatting other developer's code because it isn't "pretty".
Quick list (in no particular order, but make sure you read about Occam's Razor)
(My personal far out web design top 10 [12] designed them thinking about web content, but all are applicable to coding)
[1] http://www.victusspiritus.com/2009/04/12/stress-makes-programmers-dumber/Comments. Comment everything you do. You will thank yourself later, and so will your teammates. Besides, it makes documentation writing easier/unnecessary.
Refactor. Don't be afraid to re-do it. With proper design and good test coverage, this shouldn't be a problem. If it is, figure out why - you'll learn more from mistakes than successes.
[Edit] Er, don't be afraid to refactor I guess is how it should start :)
Don't get too stuck into the computer mode of thought. It does you little good to brilliantly solve the wrong problem with elegant code.
Customers are smart people, but they don't speak our language. And they pay our salaries. We need to come to them and learn to translate their requirements.
Think 100x longer about the code before you write it. Don't just start spewing spaghetti
Putting off writing documentation until the last minute. This is one that bites me no matter how much I try to avoid it.
For small functions, I use
int tempval = ...
and the like. I know I shouldn't, but sometimes I can't think of a descriptive name, and ... oh well.
This should set a bad example [1], while this is more positive [2] (and serious).
[1] http://freeworld.thc.org/root/phun/unmaintain.htmlDon't duplicate behavior by copy and paste code.
Don't assume anything - ask when you don't know, and comment your code when you do.
Have a look at programming anti-patterns [1].
[1] http://en.wikipedia.org/wiki/Anti-pattern#Programming%5Fanti-patternsThinking I know what the users want, without checking it often enough.
I actually listen to what the user says he wants. I later realise he hadn't a clue.
If half-year later you'll think that you are "guru" in C++ (or java or any other language or technology) then it'll be you great mistake. Your should always know a little more than other but you should think that you still don't know anything. It's a key to success in programming. Learn, learn and learn again.
If you must optimize, don't be penny-wise-pound-foolish.
I've seen people sweat over which optimization level to use on the compiler, or whether ++i
is faster than i++
, on code full of function calls (i.e. p.c. never there) to multiple abstraction layers, sapping magnitudes of performance, while saving neither cycles nor dev. hours.
I over-engineer....hence this question Ways to prevent over-engineering [1]
[1] http://stackoverflow.com/questions/1702052/ways-to-prevent-over-engineeringWriting code that's hard to read and needs lots of comments is a bad habit to avoid. Instead, you should write code that documents itself and doesn't need comments.
Here's an (artificial) example:
BAD:
if(!node.GetChildren().Size()){ // leaf node
ProcessNode(node, false); // false means not internal node
}
else{
ProcessNode(node, true); // internal node
}
BETTER:
bool is_leaf = node.GetChildren().Size() == 0;
if(is_leaf){
ProcessLeaf(node);
}
else{
ProcessInternalNode(node);
}
A general lack of consistency with my naming conventions.
I'm usually consistent enough when I'm focused on just one project. But my naming conventions tend to change slightly every year. So this can become annoying when I work on a project over a long period of time.
For example, did I name that database column CreatedDate or date_created? I just need to pick a convention and stick with it.
Not using a source control system like Subversion or Git even for toy or one-shot programs.
Telling yourself "I'll check it in later" is just like your pointy-haired boss telling you not to worry about all the technical debt because "We'll come back and fix it" which is right up there with "The check is in the mail" and "We're from the government and we're here to help".
I have the attention span of a goldfish if I'm not motivated. I'd rather dream about brewing beer than doing programming I have no interest in. I plan to carry this on until I ditch programming and open a brewery, where upon the day dreaming will probably flip back the other way...
One of my vices is more the opposite of the "Re-write everything" vice. At some point, legacy code should be thrown overboard. Perhaps not too soon, but it is possible to spend too much time trying to make something that is fundamentally broken, work again.
I always want to re-engineer everything I find "That can be done smarter" and "I can do better then that" till I end up with three different implementations of the same thing.
Posting subjective questions on SO.com in the hopes of getting more SO rep when I should be working.
Answering othe people's subjective questions on SO.com in a slightly tongue-in-cheek, sarcastic manner, and hoping that other programmers upvote my somewhat dry ramblings, thereby generating more SO rep.
Not programming deliberatly. Many programmers don't know what they are doing, they don't know why their code is working, and hence they don't understand when it suddenly doesn't work. Read "Pragmatic programmer" by Andy Hunt, it's full of good programming habits. This habit is from that book.
Shotgun programming. That's where bugs are fixed by randomly changing things here and there hoping one of them will solve the problem. Shotgun programming takes many forms:
But never, never actually analyze your code. That takes too much effort. Just make changes and re-compile!
Don't create solutions that are too elaborately coded and overly feature-rich - Keep it Short and Simple [1]
[1] http://www.faqs.org/docs/artu/ch01s06.html#id2877917While it's true that thinking about a problem before approaching it is very important, if you're not a seasoned programmer, sometimes you just need to start writing code. You can't foresee everything, and going over concepts in your head only gets you so far.
If you're anything like me, you'll find out that the code evolves and validates in your mind as you write it. Sometimes something that made sense on paper will turn out to be a terrible idea as soon as you write a function implementing it.
If you don't want to risk breaking existing code, start a Test project and try out the ideas and concepts for solutions there. It's sort of like TDD, but for people who like to experiment first, and then plan.
Procrastination.
Arrogant.
Using all kinds of weird control structures to avoid one little goto
. Everyone knows that spaghetti code is a bad thing, but one goto
does not make spaghetti code. Everyone seems to believe that goto
causes cancer and should be removed from the language. Way too often I see code that would be much easier to read and understand if it used one little if(something) goto somewhere;
instead of things like do {... if(something) break; ... } while(0);
.
I buy domains and then don't use them, and then renew them :(
It's no wonder that young folk are queueing up to avoid IT courses and the IT industry if we are really as boring as this. Apart from Dirk Eddelbuettel's comment, none of the answers come close to my idea of a programming vice:
programming while drunk at the wheel of my Porsche 911;
programming while engaged in sexual activities with colleagues;
using recreational drugs to achieve the right frame of mind before starting work at about 45 minutes before heading off to the bar for the evening.
Please, colleagues, try a little harder
Sigh
Mark
I feel I do not test my code enough, or that during testing, I let certain problems through out of a desire to move on.
Some of these come back to bite me later, which can be rather embarrassing. Iterative development is nice and all, but I wonder if I've found that fine balance between doing things 'good enough' (to meet a deadline), and doing things properly (to ensure you don't get embarrassed later).
One question i have always asked myself when doing code reviews and the like is, * Is this the result of being lazy, are there areas that could be improved ?*
By that i mean could the person have done better but skipped that bit because they
Many times there are many vital things missing, the completed polished product will not have these.
Functions & methods should only do one thing!
Avoid writing functions that are bigger than needed by breaking them into smaller pieces - look for duplicate code and place this in a helper function.
Try to break up functions & methods with more than a few dozen lines into smaller functions - this will greatly increase readability and make maintenance and testing easier.
The one thing that has always been painful is failing to spend time designing the program before writing any code. I've regretted it every single time.
Be careful about charging ahead in your own direction when five minutes talking to somebody might save you a day of effort. It's usually worth just asking somebody.
Using the debugger (and ONLY the debugger) to fix bugs or code. It's really handy and easy to do this sometimes that you end up spending more time with the debugger than thinking about the design or logic.
If you start a new programming task don't jump directly into the code. Great programming starts on paper (or in the UML-editor if you wish).
Think before you code - it will save you a lot of time by not having to throw away solutions that didn't work out.
When I tell myself, "Oh, I'm in a hurry so I'll write unit tests when I have some spare time", I never end up actually writing them. Which is why I've been forcing myself to write them first.
One terrible habit I still encounter in the companies I work for is the lack of will to extend their knowledge. Most programmers learn a specific technology and stay there. Don't evolve. Others think that the company should pay them to take a course to recycle their knowledge. I don't think that's the way to go. We, personally, must have a conscience that we need to continuous learn.
The bad habit is: don't ever stop learning!
I don't comment enough.
I know I do it, and I keep trying to fix it, but I keep coding too quickly and forgetting to comment!
Believing (without question) what you've been told, or "common wisdom".
What others tell you may be true, but often it is just an attractive idea that started somewhere and keeps traveling, like a virus.
Your brain is yours. Use it. Think for yourself.
In OO languages, not knowing about high cohesion, low coupling. Or not caring about it (which means not constantly measuring).
Not analysing anything before programming
Being too insistent on having a simple interface to things, no matter how much it complicates the implementation.
Coding while intoxicated. I always regret it the next morning.
I think I see myself in so many answers here already!
My vice of late: Adding this comment: //TODO: Refactor this later and then never finding the time to return.
For small projects, jump right into coding without having a clear design in my head; which costs me time later or at some point when things starts getting messy.
Writing:
if(variable == true) variable = false;
else variable = true;
Instead of:
variable = !variable;
Or:
if(condition == true) ...
Instead of:
if(condition) ...
Or:
if(condition) {
// Do nothing
} else {
// Do something
}
Multiple return statements from a method/procedure is a big no-no. Don't code in a 1960's COBOL style and do this--it was unacceptable in the 70's and still is today. If you have multiple returns like this, then you code is structured poorly and needs to be re-thought. Chances are, the method/procedure should be broken into smaller methods.
Limit methods/procedures to no more than 100 lines or so. Again, if you are exceeding this your code is probably poorly structured. I see new coders writing methods that are over 1000 lines long. Don't do it!
I spend a lot of time tweaking my editor, my shell, my fonts, my colours etc. I do this because when my vim-fu is rocking, then programming is a tedium free romp. I always find time to do this, and I never think it is time wasted.
So really I have 2 vices here:
Jumping straight into writing code without thinking about what you're trying to achieve and how you're gonna do it usually leads to inconsistent code that needs to be re-written again and again.
Also, don't get too attached to a particular paradigm. There are many ways to approach a certain task and one of the most important things you can learn is to choose the right tool for the job. Don't be afraid to step outside your box.
If you run into something not working the way you expect, it is possible that it is the framework's fault, but not in your (or my) case, check, double check, and triple check your code, then sleep on it and then check your code again... see it was your code and not the framework :)
Not paying attention to details.
Programming is all about details, yet it amazes me how many times I come across code where the programmer just did a sloppy job. Cut and paste jobs, duplicate code everywhere, and inconsistency across the code base are inexcusable.
It really comes down to refactoring. You wouldn't expect any other professional to just walk away when they finally got something "working". I'd hope the surgeon would pull his gloves out of me and stitch me back up when he/she's done operating.
One side note...If Visual Studio gives you a warning, treat it as an error and fix it! Don't leave that variable there if its not used. You know who you are.
Also, trying not to blatantly repeat the many good ideas above
Avoid global variables. Write every with reuse in mind. Identify common patterns and implement them as parameterized routines.
Just because you have a shiny new hammer, doesn't make every problem a nail!
This is the one I perhaps the most guilty of. I add a new tool to by arsenal and then I start going looking for reasons to use it. Just because your language added a neat new feature like say, generics or anonymous types, doesn't mean you should use it everywhere! Tried and true methods are tried and true for a reason. Just because something is new, doesn't mean that way is better.
Now, if you will excuse me, I have to go recode all of my WebForm code into MVC!
Things to avoid to me :
Things I encourage :
This is my first tought on it, I might add some stuff later ;)
Hope this help you ;)
This may sound obvious, but coding before thinking through a task/problem beforehand is still more common than you'd think. It may even be behind the lack of useful comments in code - they're harder to add later, except maybe throughversion control.
I've itched this scratch and suffered occasionally from it with logic errors that cost more time debugging since the code give results but solves the wrong problem or in the wrong way.
I'm not saying you should contemplate universal implications or have a formal definition of things, . But, a simple diagram or checklist helps provide a mental model to revisit and confirm. Mind mapping [1] tools can help for many projects, for design as well as collaboration and documentation.
In programming exercises for beginner students, I usually recommend that they transcribe or paraphrase the homework problem text to serve as comments for their code.
This reminds me of recommendations for checklists in operating rooms [2] because they significantly reduce surgical errors and patient mortality.
[1] http://freemind.sourceforge.net/The number 1 thing I wish had been emphasized in school was design patterns. The std. Design patterns have given me a new perspective on OOP and I wish my college had presented it. I've also started to try to invent my own design patterns based on rules the book outlined (mentioned below).
That book is (I think it is great): http://oreilly.com/catalog/9780596007126/
Also, take a look at: http://en.wikipedia.org/wiki/Design_pattern_(computer_science) [1]
[1] http://en.wikipedia.org/wiki/Design%5Fpattern%5F%28computer%5Fscience%29Make sure that you get your code reviewed from your peers. It always helps!
Realizing that as a developer, you're going to have expectations placed on you to solve problems that you have no clue of how to fix. You'll never stop learning new things.
Runner up: Model-View-Controller (MVC).
Also-- get used to having weeks and even months worth of dedicated hard work completely thrown away by your manager b/c she decided to change direction on a project just before its deadline.
Code first, think later.
No matter what approach you take to writing a program, it will likely take longer than you originally anticipate, especially when you are new to it. Learn to budget your time.
I agree with many of the above, but I would like to add three more; the first from "Unix Principles" that were compiled back in the early days of computing which are amazingly pertinent to today. That is create each program to
Do one thing and do it well
Look at such things as grep or awk. Many programs today try to be all things to all people and they are difficult to figure out and probably horrible to debug. This does not mean that you have to apply it to the top level application, but apply it in functions, methods etc.
The second thing is
** Do some planning on paper before starting to write code, even if you have a hot idea in your head about how you are going to write it. **
The reason for this is that you will tend to think of modifications to the basic design as you are writing the code. This means that you have to step back and re-design some of the code that you have already written. A little design brainstorming will make the whole process go better.
Pre-factor before you re-factor
The third thing is: **
Don't use a database for just a few records of a simple data structure
**
If you are using a random access record file of say 10 or 100 or even 10,000 records of some simple structure that doesn't need to cross reference another database just "roll your own" random access file or use xml and then access the data through your own code. I have had to install database programs of different types just to handle some insignificant amount of data. Databases are great for businesses that have millions of customers and a lot of tables are involved that have to access one another. But they are bloat for a few thousand or less simple records of say "Name, Address, City, State, Zip code"
Not getting an agreed requirements/specification document (or similar), signed off before writing any code.
It will kill your enthusiasm for coding rapidly when you discover that you have not hit the objective and have to re-write everything.
things that might help you become a better coder (and that they forgotten to teach you in school).
Dont repeat yourself
[1]
Command-query separation (CQS)
[2]
Defensive programming
[3]
S.O.L.I.D.
[4]
Code Smell
[5]
Smells to Refactorings
[6]
Patterns & Anti-Patterns
Software Craftsmanship
[7]
Not planning things enough.
Sometimes even a pencil and paper is one of the best programming tools. Of course, UML and other techniques can be really helpful in big projects. Writting a summary of what you're about to do also helps. Doesn't matter if it's pseudocode, or just a regular descriptions.
Conclusion, you'll develop in a quicker and more efficient way if you REALLY know and understand what you're about to do.
Programming behaviour not matching the project-class, and in general lack of project management:
For Large Projects:
Avoid trying to 'push through' a project if you get stuck. Go do something completely unproductive. (joke?) Something else and get your mind off of the task at hand... sooner or later the answer will come to you. Breaks are sometimes the best programmers true friend.
Not writing unit tests for your code is a horrible habit to get into. Learn a unit testing framework for your language of choice and try out Test Driven Development for a couple of weeks you'll never go back. The tests help you design better APIs and actually change and improve your code without fear of breaking things.
Pick a style of indentation that makes sense (if your professors are giving you lots of code samples, the easiest may be to just use whatever they use) and use it. When I try to help people in my classes I'm amazed by how some of them are totally unable to indent their code in an organized way. (I would say it usually means their thought process is equally disorganized.)
Learn other languages. If your classes are all in C++ or Java, go online and mess around with Python or Lisp or Prolog. It's fun!
If existing classes or functions don't have quite the behavior you're looking for, modify them to include it. Don't rewrite new classes/fucntions yourself. Duplication is very bad.
When your code turns to spaghetti, spend some time rewriting it to make more sense.
Comment liberally.
Use sensible names for classes, methods, functions, variables, tables, etc. Use a standard naming convention for each (camelCase, underscores, whatever... just think about it and stick to it).
Do not use IDE's or code completion to write simple programs. Instead use simple text editors like VIM, PICO or notepad.
Bad style
a=b
Good style
a = b
=
' ;) - VonC
Care too much about what other people think about the subject.
When I prototype
if(condition == true)
return;
instead of
if(condition == true)
{
return;
}
And of course I forget that I was the one who wrote it and chastise random people during code reviews.
Using very short abbreviations for variable and method names, a practice I picked up from my early days as a Fortran programmer.
Designing as I code. Part of this practice involves moving chunks of code off to their own functions as it's all coming together... except, sometimes I never get around to that "housekeeping" step, so I end up with lengthy functions and repeated code. Eventually, in all likelihood, I end up refactoring (cough throwing it all away and rewriting it).