So many times I've encountered something and thought, "I can't believe that people are actually expected to use this software."
It was bad from a user perspective: difficult to use, slow, tedious to do what you actually needed to do, unable to "get there from here".
Then once I looked under the hood, it was often worse: built upon a horribly designed data structure, inflexible with constants where there should have been parameters, no apparent thought put into its use, too many violations of acceptable practice to mention, looking as if it evolved haphazardly (which it probably did).
It's easy to bitch about stuff like this, but you often have to go to the next level to do something about it. It's amazing how much rethinking you have to do and how many tools you have to build to turn horrible software into what should have "obviously" been done in the first place.
Easier said than done. And often, some of my best learning experiences.
Understanding the thinking behind other peoples code (yes, even crap code) is one of the hardest programming skills to acquire.
I would rephrase this to learn a new programming paradigm. There are fundamental differences between static typing and dynamic typing, object orientation and functional, manual memory management and garbage collection. There are also "pure" single-paradigm languages and multi-paradigm languages. If you learn the same type of language multiple times, you're really just learning new syntax and probably a couple of extra idiosyncrasies, so it's important that you pick languages with fundamental differences.
Compare going through this learning path:
Perl -> PHP -> JavaScript -> Python -> Ruby -> Node.js
To going through this:
Java -> C -> Scheme -> JavaScript -> Erlang
For example.
C64 BASIC -> C64 raw machine code -> QBasic -> x86 raw machine code -> Turbo Pascal -> C -> Visual Basic -> Java -> O'Caml -> Delphi7 -> Python -> C++ -> Erlang -> C# -> Haskell -> F# -> JavaScript
To keep learning very different languages is also what guarantees you will be able to get a good job when your bread-and-butter language falls out of fashion. Try to imagine being a 60-year old Cobol-only programmer in the job market today. In addition to getting some experience with the actual languages, you will also get a good grip of the underlying patterns and ideas, which will make it a breeze to pick up any new language.
Another mostly overlooked skill that you gain from working in radically different languages, is to be able to work with different priorities. Java and C++ are designed for serious work. In these, you take types, error checking and exceptions seriously, you keep the code clean and robust, and you R the FM thoroughly for every single external function you call. Visual Basic, on the other hand, is designed for slapping together something that gets a small job done. Errors can be ignored, text encoding can be fucked up, functions can run into 500 lines, and that's simply something you should be comfortable with when in VB - it's copy/paste/hack/throw away all the way. C# is again very much like Java, but without the documentation attitude. Critical bits of the standard library are woefully undocumented, and you are expected to just try some code and see if it works. When in C#, just accept that and be comfortable with it.
But, most importantly when learning a new language: Adopt the mindset. Don't try for type-safe Python. Don't write slapdash C++ code. Don't try for time-critical optimized VB. Don't box/unbox everything in F# to get dynamic typing.
What type is "null" in Java? What type is the stack in C++?
Java and C++ have very little typing. You have to type a lot of types into your source code, but they don't get you anything. For every Java or C++ program, there is some set of input that results in a NullPointerException or a segmentation fault. Guess what: if you had a type system, that wouldn't happen.
Java and C++ are designed for certifications, long-lasting career, and compiling [1].
So how do they compare to Haskell, especially when it comes to types and code cleanliness?
For those who don't have Haskell listed in their path, I'll tell you: Haskell takes types a lot more seriously, but they're so different from what a C++ or Java programmer would think of as types that it's difficult to make a direct comparison. Ditto error checking, which, to a large extent, is baked into the type system such that it's a compilation error to not check for a lot of problems. Cleanliness is practically an obsession, to the point you'll wonder how anyone can write useful code in Haskell until a switch flips in your head and you begin to wonder how people can live with Java and C++. ;-)
Frankly, every language you learn should cause a switch to flip in your head like that.
I learned a lot about languages but there are many of my friends who know just PHP or Java and who are much more productive day to day than me.
My advice to someone would be to pick one language an learn it really well so you can do pretty much anything in it. Do Code Katas, make stuff all the time. When you're bored, dick around with other languages like Haskell or some of the Lisps(try to do SICP exercises).
But be productive in at least one language.
Check out some of Corey Haines's videos on practice to understand better what I mean.
I've been writing code that allows you to describe a website in data and at a high level recently, and builds you up all the methods you need to interact with it. In general, when people need to provide parameters, I also let them pass in coderefs that can be executed to provide those eg:
my $name = ref($args{'form_name'}) eq 'CODE' ?
$args{'form_name'}->( $self, @user_options ) :
$args{'form_name'};
my $form = $self->mech->form_name( $name );It essentially teaches you functional programming in Perl.
use YAML::Syck; $YAML::Syck::UseCode = 1;
Watch out though, when you take executable code from a user.
God, do I hope that the programmer that comes after me is as excited about the code-as-data, data-as-code paradigm as I am... Or at least can understand anything I wrote :)
name = args[:form_name].respond_to?(:call) ? args[:form_name].call(user_options) : args[:form_name]
Fewer sigils, no array/scalar access nonsense, real and convenient objects, etc.
As with PHP, reusing the same sigil for everything misses the point of sigils rather badly. I count five instances of two sigils in your example and each sigil character has another syntactic meaning within the same line.
my $name = ref $args{form_name} eq 'CODE' ? $args{form_name}->(@user_options) : $args{form_name};
Taking the original Perl example I would probably write it like this:
my $name = do { my $c = $args{form_name}; ref $c eq 'CODE' ? $self->$c(@user_options) : $c };
Which seems DRYer to me.
http://search.cpan.org/~sargie/Data-Google-Visualization-Dat...
This made me more conscientious about what I release ;-)
(No, doesn't count as a bug, really)
Disagree with this one. My rule is, "If you get stuck for more than 10 minutes, post to StackOverflow." I'll post my question then continue trying to solve it myself. Sometimes someone will post a good answer right away, saving me lots of time. Other times I'll end up solving my problem on my own, but I'll still learn something valuable from a comment or answer somebody posts to my question. Here's a good example of what I'm talking about:
http://stackoverflow.com/questions/6327396/set-time-part-of-...
Even when I post, if it's not quickly solved and gets very few hits, at least I justify the problem as being non-trivial... this is also useful in determining cost/benefit of even solving the problem (perhaps it's better to spend your time on other things).
I also do that aswell. But it's a bit annoying when, within 10 minutes, my (unanswered) question is the top google result for the problem (due to high keyword relevance).
If I were to add to it I stress the importance of reading books by different authors and publishers, even if they're about the same subject. This helps you get a much wider, well-rounded view and it often improves the learning experience.
I would also like to bring up the importance of reading "good practices" books and articles. Learning not only how to write good code for yourself, but good code for your colleagues to work with is an important skill to have. Writing maintainable code is often not trivial. I recommend reading Effective Java by Joshua Bloch.
This will not only improve your skills in general, but learning from the mistakes you make is probably the best way to grow as a programmer.
The main thing: always challenge yourself. When your at the inflection point of your learning curve, do something different. Expanding your boundaries will not only help you learn different technologies, but it will give you a better perspective on your actual specialties.
There might be other places to find some of these things, like other compiler texts or the actual source of some Lisp compilers and runtimes, but books are often laid out in a nice pedagogical way. Reading the SBCL or Racket source would be a steep way to get to some of these ideas.
I would amend your recommendation to say, pick the massive textbooks you read carefully. Don't suffer through big, poorly written books.
You don't get better if you don't tax your brain a little, much like how you don't get stronger if you use a winch or wheelbarrow to carry a load instead of carrying it yourself.
Still, if you're not feeling foolish often, you're not learning. Competence is deadly that way.
Of course, I see a lot of give me teh codez there, so I can see where the author is coming from. Nevertheless, I find it to be a useful tool in helping me become a better programmer.
So perhaps a more actionable proposal is to try to fix a bug, preferably one you care about, in some open source project.
It seems to work better now.
For example, where I work, we get a lot of user-submitted content, but we can't use all of it. So we need to filter. The lady who is primarily responsible for this simply doesn't have the time to vet the massive number of images she runs across to make sure they meet some basic criteria for size and quality, so I wrote a program that mostly automates it.
2. Work on poorly-run large projects with (a) performance problems or (b) code organisation problems.
3. Work on other projects with developers that use (1) to solve the problems of (2). You'll be surprised how quickly you learn when you've seen the benefits to be had by doing things better... ;)
It's just another less abstract reiteration of a few truths that encompass much more than programming.
Work with different tools. Think. Talk about what you do with other people. Do all of it a lot.
So I'll add two:
0. talk to other programmers 11. attend a Coding Dojo