... how can I develop programming skills that can be applied towards all languages instead of just one?
The key to this question is to transcend the language and think in not the language you are coding in.
WAT?
Experienced polyglot programmers think in the abstract syntax tree (AST) of their own mental model of the language. One doesn't think "I need a for loop here", but rather "I need to loop over something" and translates to that to the appropriate for, or while, or iterator or recursion for that language.
This is similar to what one sees in learning a spoken language. People who speak many languages fluently think the meaning, and it comes out in a given language.
One can see some clue of this AST in the pair of eyetracking videos Code Comprehension with Eye Tracking and Eye-Tracking Code Experiment (Novice) where the movements of the eye of a begineer and experienced programmer are watched. One can see the experienced programer 'compile' the code into their mental model and 'run' it in their head, while the beginner has to iterate over the code keyword by keyword.
Thus, the key to the question of developing programming skills to apply to all languages is to learn multiple languages so that one can distance themselves from having the mental model of one language and develop the ability to generate the AST for a problem on their own in a head language that is then translated to a given language.
Once one has this ability to use the AST in the head, learning another language within a similar school of thought (going to Befunge is a bit of a jump from Java, but not as much from Forth) becomes much easier - it's 'just' translating the AST to a new language which is much easier the 3rd, 4th and 5th (etc...) time it's done.
There is a classic article, Real Programmers Don't Use Pascal. Part of this reads:
... the determined Real Programmer can write Fortran programs in any language
There are also bits for which you can't just use the mental AST - you need to think in the language too. This takes a bit of time to accomplish (I'm still accused of writing Perl code in Python and my first Lisp code was reviewed saying "This is a very good C program.").
To this, I must point out an article published by the ACM, How Not to Write Fortran in Any Language. The third paragraph of the article (that isn't leading quotes) directly addresses the question at hand:
There are characteristics of good coding that transcend all general-purpose programming languages. You can implement good design and transparent style in almost any code, if you apply yourself to it. Just because a programming language allows you to write bad code doesn’t mean that you have to do it. And a programming language that has been engineered to promote good style and design can still be used to write terrible code if the coder is sufficiently creative. You can drown in a bathtub with an inch of water in it, and you can easily write a completely unreadable and unmaintainable program in a language with no gotos or line numbers, with exception handling and generic types and garbage collection. Whether you're writing Fortran or Java, C++ or Smalltalk, you can (and should) choose to write good code instead of bad code.
It isn't just enough to have the AST - it's necessary to have the AST that one can translate into other languages. Having a Fortran AST in your head and writing Fortran code in Java isn't a good thing. One must also be familiar enough with the language and its idioms to be able to think in the language (despite what I said at the very top).
I've seen Java code written by someone who hadn't stopped writing C code. There was one object with a main method. In this object were a bunch of static methods called by main
, and private inner classes that had public fields (and thus looked a lot like struts). It was C code written in Java. All that was done was translating the syntax of one language to another.
To get past this point, one needs to continue to write code in multiple languages, not think in those languages when designing the code, but think in them when translating the design into the code to work with the language idioms correctly.
The only way to get there - being able to develop programming skills that can be applied to all languages - is to continue to learn languages and keep that mental programing language flexible rather than linked to one language.
(My apologies to ChaosPandion for borrowing heavily from the idea he presented.)