Adjusting Learning Styles: The Transition from Launch School’s Core to Capstone
This article is a companion to my teammate Jason’s article on JIT learning. His post shows he applied JIT learning to his own project and how Launch School’s Core Curriculum prepared him to take on a variety of technical topics. I highly recommend a read.
In a quest to become an outstanding software engineer, you’ve spent months (or years) diving into the fundamentals — the building blocks of software: networking, databases, backend development, frontend development, OOP, testing, problem-solving, and more. Now you’re preparing for the job search, and want to build an awe-inspiring project to show off your resume. You start researching modern technologies and trends to mix into your application, but soon your heart sinks. React? Typescript? GraphQL? Containers? Virtual machines? Cloud computing? DevOps? Serverless? A spaghetti soup of AWS services? The list goes on. How will you ever find the time to master or even comprehend all of these things?
The answer: you probably won’t. And you probably don’t need to.
During the brief preparatory period before Capstone, my peers and I were introduced to a wide variety of topics. Moreover, the concrete learning path we had been on was now softening and widening. We will continue to encounter a great density of topics during Capstone and our software engineering careers, and the path to learning it all will not always be laid out. After having spent months (or years) learning in a mastery-based fashion, we were faced with a new predicament: how will we create and execute a plan for covering a high quantity of subjects in a relatively short period of time?
Enter “Just-in-Time” Learning
Just-in-time learning is about learning just enough, just in time, to accomplish some goal: building a project or crushing an interview, to name a couple. Toyota, an advocate for Just-in-Time production systems, phrases it like this:
Just-In-Time means making only what is needed, when it is needed, and in the quantity needed, at every stage of production.
Like a good project manager defines project requirements, a JIT learner defines learning requirements over what to learn and the depth at which to learn those things. And that depth is oftentimes shallow.
As with many other Core grads, I was accustomed to a style of learning focused on mastery. I didn’t want to give up this learning style for something less deep. But ultimately, I found that I didn’t have to give up this approach to learning completely. I would, however, need to make some adjustments.
Adjusting My Learning Style
Before moving any further, let’s make one thing clear: for someone brand new to programming, trying to immediately jump into a sea of technologies could be disadvantageous. Chris Lee mentions two prerequisites to unlocking Just-In-Time Learning:
1) A rock-solid grasp of programming fundamentals
2) Knowledge of how to learn
These two things make JIT learning feasible. But to actually learn just-in-time, we might need to make adaptations. The following sections outline my personal learning evolution in the context of my development of a small application that shows off my family’s two dogs to the world: The Smooches. (Yes, we call our dogs “the smooches”. My 8-year-old self decided on that, and it stuck.)
Getting My Priorities Straight
Like many other curious developers, I find it all too easy to fall down the infamous rabbit hole. Rabbit holes can be fun and even productive, but they tend to disrupt JIT learning. The remedy for rabbit holes is a clear set of priorities. Defining my priorities looked similar to Jason’s timeboxing strategy.
- Timebox Length: This app was a Christmas present, which gave me about 10 days.
- Learning Priorities and Knowledge/Skill Gaps: I wanted to build a React frontend and Express backend deployed on a containerized system, on a manually-configured Virtual Private Server, using AWS services like EC2, S3, and CloudFront. I had some theoretical understanding of those things, but little-to-no practice with them. I already felt a bit more comfortable with React and Express. Since my goal was to work on my knowledge and skill gaps, I decided to focus more on architecture and deployment and less on full-stack development.
JIT learning usually lends itself to short-term priorities. But we might simultaneously have longer-term priorities, such as knowledge retention. Was I to just sacrifice long-term learning altogether?
Well, not necessarily. But I’d have to be selective about what I would consciously try to commit to memory because long-term retention is surprisingly difficult.
To understand what this selection process might look like, I’ve divided knowledge and skills into four buckets:
- High-level concepts worth remembering
- Details worth remembering
- Details not worth remembering
- Procedural/skills-based knowledge
Most information we encounter falls into bucket three: details not worth remembering. How do we find the diamonds in the rough?
Focusing on the Big Picture
React is a feature-dense library for building a user interface. You could spend a decade on it. My goal was to learn enough React to prepare for Capstone and build a simple CRUD app.
Let’s imagine React knowledge as a hierarchy (that is by no means complete):
Now let’s generalize this hierarchy as a tree that can represent any topic:
In computer science land, there are well-known patterns for traversing nodes of a tree. Capstone Preppers, you know what I’m talking about. If you’ve never heard of a tree that isn’t a plant, you can skip the next two diagrams. In our case, these traversal patterns represent different ways we could progress through a topic. We could traverse/learn in a depth-first fashion with a “pre-order” traversal:
We could also perform a “post-order” traversal, starting from low-level details and working upward. But when it comes to JIT learning, these techniques just take too much time. Instead, I’ve found that JIT learning is best executed with a “level-order” traversal. More specifically, let’s call this a “selective BFS” (selective breadth-first-search) traversal pattern:
Ultimately, this was a long-winded way of advocating for a top-down approach to JIT learning. We start out with the high levels (bucket one) and work our way down to lower levels (buckets two and three) as time permits. In a real learning context, we’ll come across lower-level technicalities during our exploration of the higher levels, but we postpone plunges into the lower levels, diving in later as needed. Like pruning branches from a tree, we might selectively disregard some details and focus on relevant details. There are a few notable advantages to this pattern:
- It prioritizes the big picture: Not all information has equal value. I should probably be familiar with React hooks, but I might be fine with glossing over the
useMemohook in particular. Additionally, touching on lower-level details after establishing a big-picture context helps to reinforce the big picture. As I began to view details as support for major ideas, rather than things I have to work hard at remembering, I could begin to trek hills of information with a little more enthusiasm and a little less anguish.
- It saves time: Fixating on details has a high opportunity cost. The antidote is selectivity. My goal is to build a project, not memorize every command in the Dockerfile reference.
- It makes the lower-level details more approachable: If you see the forest for the trees, you can still observe an individual tree — but not vice versa. Even if I soon forget about
useMemo, my awareness of React hooks and memoization will make me more likely to reach for that hook when I need it. What’s more, spending time on this high-level stuff first makes it easier to retain pertinent lower-level stuff (learning mentors seem to agree with this).
If all goes well, we’ll probably come out from this with just a few big concepts that we actually retain long-term. Not only is that okay, but it’s expected. The details are now that much easier to acquire when we need them. And guess what? That’s what documentation’s for.
Side note: If you use a spaced repetition for long-term learning (myself included), your current system can be incorporated into this framework. Reserve critical concepts and the occasional important detail for spaced repetition. Stuff that you really want to remember but might forget. I’ve gone overboard in the past, and it’s not a fun experience.
Gaining Practical Experience
The previous section left one knowledge bucket unaddressed: procedural knowledge. To acquire this type of knowledge, you’ll need practical experience.
Conversations with my Capstone teammates often lean toward the more theoretical side of things. Ryan, one of my teammates, frequently reminds us of the importance of practical experience. He emphasizes that:
- Quickly following up theory with practice makes concepts stick.
- Practice itself is the end goal: if we can’t contribute to a project, we won’t be useful developers.
The key is to find the proper balance between theory and practice for the topic — a balance that major educational institutions even struggle to find. One requirement for my project involved configuring read and write permissions for my AWS S3 storage buckets. Since I was already familiar with permissions and AWS in general, I could now dive one level deeper, briefly touching upon IAM users and policies. It was just enough for my goals: I gained enough of an understanding of IAM to do it for real (which subsequently gave me procedural knowledge).
Earlier I mentioned the idea of selecting details to focus on. Practical experience tells you what details to focus on. My application needed to upload and delete to S3 buckets, so I needed to learn a bit about IAM policies. Simple. If I found myself getting bogged down in minuscule details while making little progress, that was usually an indicator that I had done too little learning: I needed to backtrack to a higher-level node.
Learning collaboratively can boost the acquisition of knowledge in all of the buckets — a phenomenon known as social constructivism. Luckily, my Capstone teammates were all able to set aside some time to meet regularly for technical discussions during Prep.
Like practical experience, communicating with peers can help us figure out what details to spend energy on. I’ve found team-based learning particularly effective for uncovering tricky edge cases. A look at two of our recent Slack conversation topics demonstrates this point:
- Using TypeScript to type data arriving from external sources
- The difference between elasticity and scalability
Earlier I mentioned that not all information has equal value. That said, nearly all information is useful in some context. As software developers, we will be tasked with utilizing lots of information that we have not internalized. For this, we can ring up our old trusty friend, the Internet. Google, StackOverflow, tutorials, ChatGPT, or the API reference itself: pick your poison. Or craft your own elegant reference notes.
To account for the increasing volume of information I now face, I’ve begun to save more resource links. Again, here is where collaboration comes in: our team continually shares useful resources with one another.
Devouring a firehose of information is not exactly pleasant. But having a proper perspective lowers the water pressure. After all, once you’ve got the fundamentals down, the expectation for you to absorb all the information streams is lower, and it’s okay if you miss some.
In this article, I formalized my informal learning strategies, but in practice, these strategies have few hard rules. I sought not to overcomplicate the learning process, but to illustrate a perspective shift that can make JIT learning more accessible. The path you have chosen is no walk in the park, but the right approach can make the demanding hike— dare I say it? — a little fun.