The following is a list of techniques, approaches, and mindsets that have worked out OK for me so far. Your mileage may vary.
Structure In Life Is Critical
I'm an introvert. I love people, especially programmers; but being social exhausts me. I don't adapt well to change. If there's a dinner reservation, it needs to be made at least a day in advance so that I have time to mentally prepare. For me, having structure in life is the only way that I can function at a meaningful level.
I go to sleep between 9:30 and 10PM and I wake up at 5AM. I did sleep in a little bit between Christmas and New Year's, which was luxurious. But, other than that, I keep the same exact waking schedule 7 days a week. By keeping my "awake hours" consistent, it allows me to build structure into the rest of my day and allows me to actually plan out my time (although I tend to really live day to day in terms of long-term planning). More than anything, have structure just makes me feel comfortable and relaxed. And, when I'm comfortable and relaxed, I'm most productive.
Have Dedicated Time To Learn And Research
With my consistent and predictable schedule, I can actually plan to have "deliberate practice" (ala Geoff Colvin in "Talent is Overrated" and Malcolm Gladwell in "Outliers"). After I wake up and shower, I sit down and I partake in deliberate practice from about 5:30AM to about 8:30AM. Often times, I am working towards writing a blog post. But, I'm also happy to just read up on a topic, or watch a video, or experiment with some new code.
When I was a bit younger, I think that I focused too much on trying to write blog posts. This caused me to shy away from larger topics that would inhibit my ability to produce posts. But, as I've gotten older, I've embraced the idea that the learning is more important; and, that if I can't write a blog post for a few days, such as when trying to wrap my head around Redux, that's OK. Life goes on.
There Are No Days Off From Learning
There are days off from my job; but, there are no days off from my learning. As I said, I keep the same sleep schedule 7 days a week. Which means that on Saturday and Sunday, I'm up at 5AM (with my alarm clock) and at my desk learning from 5:30AM to [at least] 8:30AM. It's not always easy, but I think the consistency and the structure is critical.
Additionally, I always have a podcast ready to go. Whether there's a car ride to the market or a long dog walk, if I'm going to be away from my desk (and alone), I have a postcast to listen to. It doesn't even have to be about a technology that I use (ex, Ruby Rogues); when you listen to smart people talk about solving problems, you will learn something!
Always Have Something To Learn
Whenever I think of something to learn or to research, I email myself. Immediately. I have a special filter setup in GMail that looks for a specific subject line and then filters those emails into an "Research & Development" inbox. This way, I always have a queue of topics that I want to dive into when I have some free time. These aren't broad topics like "Learn Redux"; rather, they're small, action-oriented topics like "try moving Redux middleware into provider configuration phase."
I don't necessarily tackle these items in a top-down manner. I pick the right one for my mood and general level of energy. If I'm particularly tired, I choose a topic that feels easy (or more emotionally satisfying). When I'm energized, I pick a topic that feels more challenging and intimidating.
Writing About It Helps Remember It
When I trip over something in programming, I write about it. When something surprises me, I write about it. When I'm just excited to have used a new feature, I write about it. I try not to write something that simply echoes the documentation; but, other than that, no topic is too small, too esoteric, or too boring to write about. Writing about technical detail is a wonderful way to build out a strong mental model that actually sticks over time. I attribute my ability to remember detail to the act of writing.
Err On The Side Of Re-Inventing The Wheel (At First)
When I face a new challenge or have to deal with a 3rd-party API, I try to write custom code for it before looking to see if there's an existing library that supports it. Yes, a very large part of this is done because I just love and want to program. But, I honestly do think that this approach helps me learn more about the topic at hand. It's how I've learned about signing requests and generating message authentication codes and producing cryptographically-strong random values and serializing JSON Web Tokens and implementing Base32-encoding by using bit-wise manipulation.
All of those things (and many more) could have been done through some library call. But, I wrote the code that implements them. And, I learned a lot while doing it.
Of course, I don't always get it right. Or catch all the edge-cases. Or can even figure out how to implement the dang thing. And, at that point, I use a [hopefully vendor-supplied] library. I have nothing against using a library; I just enjoy trying to write the code first.
Harden Existing Skills Before Learning New Ones
In the world of programming, there's a ton of churn. And, a lot of people who enjoy nothing more than immediately jumping on the next hot technology. I try to avoid new technologies, for at least a while. I try to harden my existing skills before trying to solve a problem with a new technology or methodology. They say, "choose the right tool fo the job." But, the way I see it, the tool that I know best is going to be the right tool, even when it's suboptimal.
Enjoy The Game Of Being Prideful About Your Language / Framework / Technology
Nobody likes a zealot. And don't be close-minded about other technologies or frameworks. They're probably all great. But, I do think there's a lot of value in "playing" at being prideful. If you see another language or framework do something cool, "playfully take the stance" that your language or framework is better. And then sit down and figure out how to use your language of framework to accomplish the same thing. You'll learn a ton along the way. You'll force your brain to think differently. You'll challenge your preconceived notions. The "power of constraint" can be a magical tool for learning.
Always Be Able To Explain Your Choices
Albert Einstein said, "If you can't explain it to a six year old, you don't understand it yourself." In the world of programming, I try to borrow this mentality when it comes the choices I make. Whenever possible, I try not to make a choice unless I actually understand why I'm making it and can explain the value to someone else (if I had to).
Take Immutable data for example. People love it. They're crazy about it. But, I have yet to use it because I can't point to anything in the code and explain the value-add of Immutable data. And if I can't explain why I am doing something, I don't do it. Or, I embrace the fact I have no idea why I'm doing it and just go with it until I'm smart enough to make an informed decision.
Now, this doesn't mean that my decisions are always right. My thinking and my methodologies have changed a lot through my career. Decisions that I thought were awesome - and that I could explain at the time - turned out to be unfortunate choices. But, that's just the learning process.
Read The Documentation
For me, there is no better source of learning than actually reading the documentation or the books on a topic. I remember when I first got into ColdFusion, I woke up ever morning and spent time reading the "ColdFusion MX Bible". It probably took me weeks; and a lot of the information never got used (LDAP? What the heck); but, at the end, at least I had a sense of the entire landscape of the language. Similarly, when I learned AngularJS 1.x, I poured over tutorial and most of the documentation. (I hope to do the same thing with AngularJS 2.x quite soon).
Even if it doesn't all make sense at first, I think there's value in at least getting a sense of what is out there. It helps you understand what is possible so that, later on, you can have some inkling in what to do or where to look things up.
Read The Source Code
While I love documentation, it's not always clear. When in doubt, read the actual source code. I can't even being to tell you how many marvelous gems you will pick up from reading the source code of a library or a framework. Not to mention that it will actually teach you how something works.
There's not a week that goes by where I don't open up the AngularJS framework vendor code and dig into how the AngularJS team implemented something. It never gets old. And it's always inspiring.
Be Intensely Consistent In Your Coding Style
I am a maniac when it comes to code consistency. I have a style that I like to follow and I act as if the consistency and adherence to that style is as important as the quality of the code itself. Consistency is part of my DNA. When I look at code that is inconsistent, I can feel it my gut. It makes my uncomfortable. I need to fix it. I have trouble even writing "throw-away code" that has inconsistent formatting because it makes me twinge.
I truly believe that when you are maniacal about consistency, the quality of your code gets better. Bugs are either prevented; or, they are much easier to find because they usually stand out as a blemish upon the beautifully organic shape of your syntax tree. I also think that once consistency is a first-class citizen, writing code becomes faster because there are many things that you don't have to think about - they just happen automatically.
Of course, my personal style has changed a lot over time (Hungarian notation, what was I thinking?!). But, that doesn't mean that I am any less intense about my consistency at any given moment in time.
Don't Over-Tool Your Development Workflow
When you go to the gym, you can either use gloves; or, you can build calluses and force your body to adapt to the stress and strain of steel knurling.
In programming, I view tooling in much the same way. I use Sublime Text and the only plugin that I have is for syntax highlighting. I don't use linting. I don't have any documentation plugins or code insight. I don't have unit tests constantly running in the background. I don't have any refactoring tools. I don't use snippets or macros. I have, what is basically, a really high-performing, developer-friendly text editor.
This approach forces me to look stuff up. The reason that I know, off-hand, that "minutes" in the dateAdd() function are represented by "n" not "m" (since "m" is for "months") is because I've had to look it up a whole cat-lot of times. And doing so has built up a callus in my brain that now retains that information. It's the same reason that I know that the RegEx pattern is the first argument in reMatch(), but the second argument in reReplace(). These rules are a part of my being now - they're how I see the world.
I am sure you could try to argue that this approach makes me horribly inefficient. The same way that you could argue that one should always wear gloves in the gym. But, all I can tell you is that I enjoy it. I don't see it as a problem or a barrier to efficiency. But then again, I don't wear gloves in the gym and I love calluses.
So, that's how I get through my day. This might connect with some of you and seem completely off-putting to others. I think we all have our own way of approaching life and learning and we all have our own strategies for success. These are my strategies.