Well I'm new to these boards and don't have a kernel, OS, or anything to brag about, so with that caveat out of the way, here's my advice
I'm actually going to recommend the exact opposite of the OP. I think as a beginner you should decide what you want to do, pick your language based on that, and then learn it deeply.
The rationale for this is that once you learn something that deeply, the underlying design is more apparent to you than it is if you know it superficially. You'll see the good, the bad, and the why. Understanding the tradeoffs in the design of your language of choice will be invaluable for you, even if you're using other languages.
Quote:
So generally, while abstractions and reuse are definitely good things, I would first write specific cases, and only when I see myself repeating the same pattern over and over again (sometimes twice is enough), I turn it into an abstraction instead.
quoted because it bears repeating.
Don't do something because it 'feels' right. The KISS principle. Lots of people quote it, few do it, and that's a shame.
Think about what you're doing.
Think about how you're doing it.
You wouldn't believe how much time I've seen people waste because they're afraid to waste time. If a script needs to be written to automate something
write the damned script. If you find youself spending a lot of time maintaining documentation, project scheduling, etc, stop and think about how to lessen that.
You'll find youself more productive in the long run.
last but not least.
If you're building a system you've never built before, don't think about it, just build the damned thing. You're going to muck it up. You're going to do things you regret. That's what experience is, doing lots of crap you wish you hadn't.
It's more important to jump in, get your feet wet, and learn from the mistakes then it is to not make the mistakes.
And related to this, if you're not struggling, you're not really learning. Set your goals higher.