How I learn a new programming language
Created // , updated // 2023-08-01
TL;DR // I have a well-defined reference project that is language-agnostic. When learning a new programming language, rebuild that project in the new language. Make sure the reference project exercises key features (input, output, data, libraries).
There is one go-to project that I rebuild every time I'm learning a new programming language.
It's a simple project. But it has enough to make me learn the new language's features, resources, and tooling. I've built this project many times over the past 20+ years while learning Perl, PHP, Python, Drupal, Unity, NodeJS, C#, Java, Dart, ... You get the picture.
The project requirements
Though the actual project itself isn't that important, I'll describe it here to explain my approach.
It's a simple music catalog. It needs to:
- Find all MP3 files anywhere under a given folder
- Get the artist name and album name from the folder structure
- Get the album year and genre from the MP3 file (using ID3v1 metadata)
- Create a text file that lists all albums (sorted by artist, then by album year)
It's not interactive. It's not a website. It doesn't need to be hosted anywhere. It will very likely result in a command-line application.
Why this project?
There are a few reasons:
- It's complicated enough
- I need to learn various parts of the language (strings, objects, arrays, file I/O, simple input, 3rd-party libraries, etc.)
- It's small enough
- I can finish within a short amount of time (a week vs a month)
The important thing is for the project to be well-defined and clearly understood. This gives boundaries and focuses your effort on learning the language instead of figuring out the requirements.
Example
Let's describe the folders and files I would have, and what the sample output would look like.
Assume there is a folder name per artist, and then a folder per album. Inside the 'album' folders are MP3 files.
Assume that each mp3 file has valid ID3v1 metadata defining the album's year of release and genre.
Imagine these are the folders and files you'll be processing:
└── music
├── Porcupine Tree
│ ├── In Absentia
│ │ ├── 04 The Sound of Muzak.mp3
│ │ └── 11 Strip the Soul.mp3
│ └── Deadwing
│ ├── 01 Deadwing.mp3
│ └── 04 Halo.mp3
├── Rush
│ └── Moving Pictures
└── The Mars Volta
├── Amputechture
│ └── 02 Tetragrammaton.mp3
├── Frances the Mute
│ ├── 01 Cygnus Vismund Cygnus.mp3
│ └── 02 The Widow.mp3
└── The Bedlam in Goliath
└── 03 Ilyena.mp3
(But remember, your actual solution should handle any number of folders and files.)
The expected end result would be a file mp3catalog.txt
that looks something like this:
Porcupine Tree, 2002, In Absentia (Progressive Rock)
Porcupine Tree, 2005, Deadwing (Progressive Rock)
The Mars Volta, 2005, Frances the Mute (Progressive Rock)
The Mars Volta, 2006, Amputechture (Progressive Rock)
The Mars Volta, 2008, The Bedlam in Goliath (Progressive Rock)
The output shows there are two albums by Porcupine Tree, and three by The Mars Volta.
All albums are sorted by artist name first, then by year of release.
Note there is no entry for Rush because no MP3 files were in the folders, even though there was a folder for an album.
How do I start?
Since I've solved this problem multiple times already, I've already done the hard work of figuring out how to break it down into smaller tasks.
If we think through the requirements, here are some tasks I need to do.
Learn...
- How do I pass the folder name I want to process to the application? (e.g., command-line arguments)
- How do I read all folder names from a starting folder? (e.g., recursively crawling the file system)
- How do I only get the folder names with folders containing MP3 files inside? (e.g., pattern matching filenames)
- How do I read ID3v1 data from an MP3 file? (e.g., binary file I/O, or incorporate a 3rd party library)
- How do I associate albums (found by folder names) with artists (found by folder names) (e.g., how do I use arrays, objects, lists to maintain a data structure)
- How do I associate proprties with album data (e.g., data structure choices, for album year and genre)
- How do I sort my data in an arbitrary way (e.g., by album year, by artist name)
- How do I write formatted text output to a file (e.g., file type and permissions)
Decide...
- What do I do if the output file already exists?
- What do I do if there are multiple MP3 files in a folder, and they don't have the same album year and genre?
- What do I do if none of the MP3 files in a folder have ID3v1 data?
- If there are errors, how do I handle them?
- How do I display errors to the user?
This is just a "small" and "simple" set of requirements right?
Now you have a nice list of smaller problems to solve in the new language. On their own they're not particularly hard. But they force you to learn many aspects of the language.
You might ask why we're getting some info from the folder name (Artist and Album name), and some from the ID3v1 metadata (genre and year). Shouldn't the ID3v1 metadata have all of it? Yes, probably. But the intention is to force us to collect and merge data from different sources.
Would it be better to just learn from a tutorial online?
When I finish the project, I won't be an expert in the language. Not even close.
So what did I accomplish?
I learned how to solve my problems. That means I had to search for solutions and understanding. I had to find (probably) multiple sources online that could help. I probably had to struggle to get answers.
That's a very different experience from most tutorials.
In a tutorial you start with Step 1. You copy-and-paste things. You repeat with each step until you get to the end. The tutorial is designed to work. It isn't designed to teach you how to research and find answers in your new language's ecosystem.
Simply: many tutorials are passive experiences with limited long-term benefit. (Yeah, that's a fairly biased perspective.)
My goal isn't simply to implement my project. It's to prepare myself to tackle future challenges. Throughout the process above, I learn about the language's ecosystem, platform, support channels, and where to find good information.
Summary
Define a project that you can build in a week. Try to make sure the project doesn't require a specific language or framework. Make sure it's complex enough to be worthwhile, but small enough to be achievable.
Use that as your "reference" project whenever you're learning a new programming language or framework.
The primary goal is to accomplish something real and learn about your new programming language's ecosystem and sources of support. Online tutorials don't always provide that!
// ka