Learning Fluency, by Sara Simon is a really interesting article and you should definitely read it. It’s kind of hard to summarize, what I got from it was that there are a lot of parallels between learning natural languages and learning to program, one of which is that rote memorization is both really useful and really underrated. Variables and loops are really boring for experienced programmers (which I’m suspicious is why most programming tutorials zip past them pretty quickly), but just like it’s really hard to tell someone how to get to the grocery store in a new language until you’ve memorized enough words, it’s really hard to build a program before you’ve memorized enough programming constructs.

Another good point Sara makes is that not everyone learns the same way. Some people are happy to jump into a project and learn as they go, and other people need more structure to get started. That doesn’t make anyone wrong, but it does mean we need resources for more than just one kind of learner.

Learning Fluency is a bit of a long read but it won’t take your whole lunch break either.

This particular question is about learning a new codebase at work, but I think there’s plenty of stuff here that would carryover to learning the codebase of an opensource project you want to contribute to.

When you want to learn a new codebase, the very first thing you need to do is get it to build on your machine. Deliberately breaking things is an extremely useful tool when you want to understand a codebase, if you can’t even build the app you have no chance of figuring out if you broke it or not.

At work there should be another dev around who can sit down with you and help you get everything set up so you can compile, if you’re working on an opensource project you’re going to have to rely on docs, maybe a community chat like slack, gitter, etc, and sheer stubbornness.

Next you need to be able to run it or at least run the tests (if there are tests). This can be a lot more work than just getting the app to compile. For example, the app I work on at my own job compiles really easily but it won’t run unless you have all the environment variables set up correctly and the database and cache and everything installed. You’re probably going to want that coworker’s help here too. If you’re lucky your company has docs you can read and if you’re very lucky they’re even up to date, but at most places I’ve worked the development environment setup process was never written down, only passed down orally.

Quick aside: I’ve said this before, but if your company doesn’t have any docs, write them! Seriously, you’ll make things so much easier for the next dev, who might even be you. If your computer dies on you and you need to get setup again in a hurry, you’re going to be really grateful if you can follow the docs instead of desperately trying to remember how to do that one tricky bit.

Depending on how your app works you may also need help creating an account for yourself so you can actually log in and use it. Once you can build, run, and log in (if you need to), you can really start digging into the code.

What makes the most sense to me is starting from the UI and working my way in from there. It also really helps me to have a goal, like a bug to fix or a small feature to add. I get lost if I just sort of wander around a codebase trying to figure out how everything fits together, having a goal helps me focus.

It’s also totally okay to ask another dev for a quick overview of the app, having a bit of context can make it a lot easier to figure out how everything fits together. Customer documentation can be really helpful here. Sure, it won’t tell you which controller handles the data for the user details page, but it will tell you how to get there and what you can do there.

Eventually you’ve got to get in there and start looking around, though. I poke around the UI until I find a screen that looks like it could be related to the thing I want to do, then I copy some text from that screen (ideally something that looks distinctive) and search for it in the code. Most of the time this is helpful but sometimes the text you thought was distinctive really isn’t, you may have to search for a few different things before you find something that gets you useful results.

If the app is a webapp it often helps to open up the network tab in your browser dev tools and look at the calls the frontend makes to the server. If you’re not sure exactly which endpoint is actually getting called this can clear things right up. Don’t be afraid to add more logging either, just try to remember to clean it up when you’re done :) I do that all the time when I’m trying to figure out exactly what my app is up to. If you want to get fancy you may even be able to attach a debugger to your running application and step through the code one statement at a time. I have this irrational dislike of doing that (I find stepping through the code tedious and would rather just throw in another System.out.println), but if it works for you, great!

Once you find the right server calls it should be fairly simple to trace your way back through the code all the way to the database (or other data store) if you need to. I mostly work in Eclipse, so I’m working from the assumption I have good IDE support and can easily navigate the project once I decide where to start. If you aren’t using an IDE that makes it really easy to find the definition of a class or method, you’re just going to have to do a lot of searching.

IDEs can only do so much for you, though. When I’m trying to figure out a complicated part of the code I’ll sort of draw myself a map so I don’t get lost. That is, I’ll write down, either on paper or in a text file, exactly what calls the method I’m looking at, and what calls those methods, and what calls those methods until I’m clear on how everything fits together and where exactly that one bad parameter came from.

Like I said earlier, breaking stuff on purpose can be a great way to verify that you understand how the pieces fit together. Once you think you know where the problem is / where you should add your new feature, try commenting out the body of a method and seeing if things break the way you expect. If they do, great! If they don’t, hey at least you found out sooner rather than later that you were wrong about how it works. Another good way to break things is to give them bad data. I do that when I want to know if my request is even making it to the part of the code I’m interested in – if it doesn’t break the way I expected then I know I’m wrong about what the code is actually doing.

If one screen or endpoint or whatever just doesn’t make any sense to you, try another one! You may just need to see more of the app before things start coming together, or you may have just had the bad luck to stumble across an especially tricky part of the app. Keep trying, and ask for help if you need it, you’ll get it.

Speaking of asking for help: most developers hate doing it, but it really is okay to ask for help if you get stuck. Especially if you’re a junior, it takes practice to get good at finding your way around new codebases. Five minutes of explanation by someone who knows the code could save you hours of confusion and frustration. The faster you get up to speed on that new codebase, the more help you’ll be to your coworkers, so it’s actually in their best interests to interrupt them (after trying to figure it out on your own, of course) to ask for help.

One last tip: it takes months, literally multiple months, to really be productive at a new development job. If you feel stupid and useless, that’s a) not true, and b) totally normal. You would never tell a new hire that they’re an idiot for not instantly figuring out a new codebase, so try to be that nice to yourself, okay?

Unrelated image from pexels.com to make this post look nicer in social media shares.

I think one of many reasons it’s so hard to learn to code is that the people doing the teaching have all forgotten what it was like not to know how to code, so we skip over some really important basic steps because we think they’re inherently obvious. Case in point, this poor redditor who nobody ever taught how to work through a piece of code with a pencil and paper. I had to read the question a couple of times to understand what they were even asking, it just didn’t occur to me that someone wouldn’t know how to trace through code manually.

At the end of the loop x = 1 and y = 0. These are the same values we had after we went through the loop the first time, so now we can be completely sure the loop never ends. After each time through the loop x is either 1 or -2, there’s no way for it ever to be 7 or more.

That’s it. Working through code with a pencil and paper is just keeping track of what values all of your variables have and swapping out variables for their values. It’s really tedious, that’s why we make computers do it :) And to be clear, you’re never expected to be able to work through complicated code like that purely in your head. Everybody else needs a pencil and paper too, there are just too many details to keep them all in your working memory.

Okay, so if working through code with a pencil and paper sucks so much, why does anyone do it? Because it gives you a really solid understanding of what the computer is doing, which you’ll need later when you start building more complicated things. For a simple loop like the one above you can just throw that snippet of code into an IDE, run it, and see what happens, but you can’t even start building bigger things without a foundation of knowing what the computer is doing when it runs your code.

Loosely related image from pexels.com to make this post look nicer in social media shares.

The more I read about the struggles beginner programmers have and the more I mentor at Ladies Learning Code workshops, the more I think that repetition is seriously underrated when it comes to teaching anything technical.

When you’re learning a language or an instrument or a sport or a physical skill like plumbing or carpentry or even math, which is similar to programming in a lot of ways, you expect to have to repeat the same thing multiple times before you remember all the details and get it right every time, but somehow when you’re learning to code we assume you should only need to be told how a for loop works once and you’ll understand it perfectly right away and remember it forever. That’s just not how our brains work and that’s why I think repetition is so underrated.

It is completely normal to need to write a lot of for loops before you get it right every time. Some people do pick up programming concepts very quickly but that doesn’t mean you’re dumb or abnormal if it takes you longer. Something like a for loop (or anything programming construct) seems simple once you understand it, but there are actually an enormous number of fiddly little details you have to keep track of to get your loop to work. You know what’s a great way to learn all of those details so thoroughly you hardly even think about them anymore? That’s right, repetition!

Programming isn’t just a matter of understanding the concepts, you’ve also got to learn them so thoroughly you don’t have to think about how to write a loop, you just write one when you need it. Without that thorough of an understanding, programming is like trying to speak another language by looking up each word individually in your [other language] to English dictionary. That’s one way to learn, but you’ll probably just be miserable and frustrated and forget what you were trying to say in the first place before you’re even halfway through your sentence.

Come to think of it, maybe the kind of drills you do when you’re learning a language could help people learn to program without spending so much time worrying that they’re just not smart enough.

Anyway, repetition is seriously underrated and I wish we collectively talked more about how much practice it takes just to pick up the basics of programming, let alone the complicated stuff like deciding how to structure your code or what to name things (still one of the hardest problems in programming :) ) I think a lot of programming tutorials assume that you know you need to practice without explicitly saying it or without making it clear just how much practice you need. I have to admit I wouldn’t want to write pages and pages of very similar programming exercises either, but it’s not so hard just to say that programming takes practice and you’ll probably need to go through the tutorial a few times before it sticks.

If you did a tutorial or a workshop just once and didn’t instantly become a good programmer, congratulations, you’re normal! If you keep at it, you’ll get there.

Unrelated image from pexels.com to make this post look nicer in social media shares.

I was talking with a friend who’s learning to code the other day, and the subject of the wall came up. Not the one that keeps the wildlings out, the one everybody slams into when they’re learning to code. Learning to code starts out great, there are so many tutorials that break things down really clearly, but once you’ve got a handle on the basics and want to move on to building your own projects, that’s where you hit the wall. It’s a huge leap from following tutorials where all the hard decisions are made for you to building your own projects with no one standing by to tell you where to start or what database to use or what your UI should look like.

The single thing I most want you all to know is that hitting the wall is normal. It happens to everyone. It absolutely does not mean that you’re dumb or not meant to be a programmer or that you’ll never get over the wall.

As a bit of an aside, I think the number of beginners who hit the wall and assume they’re just not smart enough to be programmers says more about how bad we collectively are at teaching programming than about the intelligence of anyone who hit the wall and walked away. I’m suspicious there’s a connection between how easy it is to write total beginner tutorials and how many of them there are, and how much harder it is to teach people to break down a problem and how few tutorials there are for that.

But anyway, I have some ideas for people who have hit the wall or who can see it in the distance and are getting worried.

One of the coolest things about programming is how many open source projects there are. Find one that you like and take it apart to see how it works. Search for text from the UI in the code and see if you can change it. Throw log messages all over the place to make the code show you what it’s doing. See if you can find some constants in there you can mess with. And don’t feel left out if you want to make games, those can be open source too.

Once you’ve found a project you like and have some idea how it works, see if you can change how it works. Let’s say you found a simple todo list app. Can you add due dates to your list items? Or subtasks? Could it play a sound and/or an animation to congratulate you when you check something off? Could you add a new feature like recurring tasks or email reminders? If you don’t have an open source app handy, just take a tutorial and mess with that.

Speaking of tutorials, if you do enough of them you’re going to start seeing similarities. Most apps have some sort of UI, some sort of data model, maybe a way to save that data for the next time you open the app (that’s pretty advanced, though, don’t worry about it right away), some logic about what users are allowed to do (like due dates can’t be in the past or players can’t have more than x hitpoints no matter how many health packs they use), maybe some communication with other APIs (but again, that’s advanced, don’t worry about it right away), and honestly, that’s pretty much it.

You can try mashing up different tutorials or open source projects too. Let’s say you have a tutorial for a driving game and one for a game where you run around and collect coins or stars or whatever. What if you could drive around and collect stars? What if you had tutorials for a todo list app and a weather app and mashed them up to make a little morning dashboard for yourself?

Don’t forget, you don’t have to do it all yourself. There are great communities like CodeNewbie, /r/learnprogramming, CodeRanch, (and lots more if you do a little Googling) full of people who will help you out.

First of all, each problem in Exercism has a set of unit tests, so you don’t have to wonder if you’re doing it right, you can just run the tests and know for sure. The tests are also great for experimenting with your code and seeing if you can make it easier to read or easier to change without breaking it.

The problems are also carefully chosen to help you learn concepts that are important to each language. Just because you can solve a problem in a certain language on a coding challenge site like HackerRank doesn’t mean you’re learning anything interesting about that language in particular. I know that’s not really what challenge sites are meant for, but I’ve seen them recommended to a lot of people who are learning and think it’s important to be clear about what challenge sites are good for (general programming concepts) and what they aren’t necessarily good for (learning individual languages).

And finally, Exercism directly incorporates both giving and receiving feedback. Obviously getting feedback is helpful – to directly quote the Exercism site: “You can write FORTRAN in any language, as the saying famously goes, but with enough feedback, you’ll quickly find yourself writing the language the way it wants to be written.” – but giving feedback is seriously underrated. To tell someone what you think of their code, you have to read it carefully and then think seriously about what makes code good or bad. That’s enormously helpful when you’re new and don’t really understand what “good code” means yet, or when you’re new to a language and just don’t know the best way to do things in that particular language.

Slightly related image from pexels.com to make this post look nicer in social media shares.

One of the most common misconceptions I’ve heard about programming is that you have to be a math whiz to be a good programmer. I’ve mentioned this before but I want to attack that particular stereotype more directly.

It is true that there are similarities between math and programming – programming uses some math terms like function and variable, it’ll be a lot easier to get things onto the screen if you understand coordinate systems, and of course to do math or programming you spend a lot of time manipulating symbols and thinking abstractly, but you know, programming is also a lot like language. I mean, they call them programming languages for a reason. To quote Hal Abelson, Jerry Sussman and Julie Sussman’s book Structure and Interpretation of Computer Programs:

First, we want to establish the idea that a computer language is not just a way of getting a computer to perform operations but rather that it is a novel formal medium for expressing ideas about methodology. Thus, programs must be written for people to read, and only incidentally for machines to execute.

Programming is fundamentally about communication. Not only are you communicating with the machine, you’re communicating with your future self, the rest of your team, and potentially other teams if you end up working for a large enough company. And that’s just when you’re writing code! You’ve also got to make sure you’re building the right thing and let other people who are waiting for that thing know how it’s going. You know what’s great practice for communication? That’s right, English classes! Sarah Mei has a great blog post about the same point I’m trying to make in this one, here’s an especially interesting quote:

The students I saw – all adults – came from a wide range of backgrounds. People with a math background did fine, of course, but people with a heavy language background often did better.

Nobody seems to have an official study on this, but I think there’s something there. Language requires just as much abstract thought as math does, with the added benefit (to your communication skills) of failing your classes if you can’t make yourself understood to anyone else. As a bit of an aside, the biggest problems I’ve run into at work have never been problems of pure programming skill (although those ones do suck a lot), they’ve been communication problems with team members, other teams, management, other departments entirely and other offices.

And to stick another nail in the coffin of the idea that programming is math, I’ve been a developer for ten years now and the most complicated math I’ve ever had to do at work is stuff like “if I have a div that’s x pixels wide and y pixels tall and I want it centered inside another div that’s a pixels wide and b pixels tall, what should my margins be?” I used to believe that programming was math, and some programming is certainly math heavy, but it’s hard to argue with the lack of math in my day to day job over ten years and four companies.

So given that programming is not math, why do so many people think it is? I’m going to quote Sarah again because she already said it really well:

When programming was just getting started, early in the last century, we used it to solve highly mathematical problems like calculating missile trajectories and decrypting secret messages. At that point, you had to be good at math to even approach programming. Tools, such as programming languages, were designed specifically to solve mathematical problems, because those were the ones we thought it was worth spending money on. Computers were for doing math.

I think another issue is the way we teach programming (credit where it’s due, I stole that idea directly from a comment on Sarah’s post). Computers are great at doing boring and tedious calculations, plus it’s easy to tell them how to do it, so why not start teaching programming by having students make the computer calculate something for them? It makes it really easy for the students to check their work too – assuming they’re able to do the math problem themselves, they can easily check if the computer got the same answer.

That assumption can be a real problem, though. If you can’t do the math problem or don’t care about the math problem, you end up effectively shut out of programming, something you could very well be great at, because of something that has next to nothing to do with the actual job of software development.

If you can do basic arithmetic and deal with the concept of variables, congrats, you can be a programmer! That is literally all the math you actually need!

Unrelated image from pexels.com to make this post look nicer in social media shares.

In college our first Java classes used a text editor (TextPad), not a full featured IDE like Eclipse, and compiled and ran our programs from the command line. When we finally started using Eclipse, I was kind of pissed off that we’d spent so much time slowly and painfully debugging our code when Eclipse could’ve just told us exactly where the problem was. Knowing what I know now, I totally understand why our teachers did it that way, but I don’t remember anyone doing a particularly good job of explaining it at the time.

For anyone out there wondering why on earth they have to do things the hard way when they could just use a tool that makes things so much easier, the answer is that the tool doesn’t actually make things easier.

It sure seems like it does once you’ve got the basics of coding down, but until then it’s just another complication that you really don’t need when you’re already trying to learn something extremely complicated. Take this question I found on reddit for example: you can have perfectly good code but be unable to run it because your IDE isn’t configured correctly. IDEs are powerful tools, and any powerful tool can hurt as much as it helps. If you already know how to write code, compile it, keep track of your files and build path and everything, then IDEs are great. If you try to learn all those things plus how to use an IDE, how to set it up, and how to recognize and fix problems with your configuration if you mess something up all at the same time, you’re going to have a bad time.

You know how your teacher always said to add one a thing at a time when you’re writing code so that you know what caused it if something breaks? That counts for tools, too. If you’re not already good at tracking down what’s wrong with your code, you’ll have a terrible time figuring out whether your code is actually wrong or whether your IDE isn’t configured right.

IDEs can also hide stuff from you that you actually will want to learn, even if it’s a pain while you’re learning it. With java in particular, an IDE can make it seem like you just write code and it runs by magic. That’s not helpful once you start working on projects that need to be run outside of the IDE. You will need to know how to compile your code, what settings you need to get the right output, where that output ends up, and how to use/deploy the compiled code, none of which you’ll learn by hitting the run button in Eclipse.

I can even see the point, as infuriating as it was at the time, of making students manually find issues like missing semicolons without the help of an IDE. The level of attention to detail you learn by finding your own missing semicolons is absolutely necessary to track down the kind of subtle logic errors an IDE can’t help you with. I don’t believe there’s any way to learn that without spending a lot of time being very very frustrated, but it’s an extremely useful skill and one that every programmer will need sooner or later.

If there’s a better (and less frustrating) way to learn to program I’d love to hear it, but I’d be very surprised if there’s a non-frustrating way to learn a fundamentally frustrating skill.

The gist of his talk is that “boring” (stable, commonly used, not shiny and new) technology is awesome because you can trust it, you can get help when you need it, and you can focus on building something useful instead of fighting with your tools.

Even if you’re a beginner programmer and nowhere near ready to worry about whether your production database is going to crash, it’s still good advice. Well known, commonly used tools are way easier to learn because they’ve been around long enough to have docs written for them and to have the majority of the bugs worked out of them, they’ve been used enough that somebody else has probably run into the same problem and asked about it on stackoverflow already, and because so many people use it, even if your exact question hasn’t been asked already somebody out there can answer it.

For example, take a look at the number of questions tagged Java on stackoverflow versus the number of Kotlin questions. When I wrote this post, Kotlin was closing in on 4k, where Java had 1.1 million. I’ve heard good things about Kotlin and I’m not saying it’s a bad language to learn, just that you’re going to find answers a lot more easily with the language that has over 200 times more presence on stackoverflow. Not that stackoverflow is the be all, end all of programming language popularity, but I think it’s a decent measure of how many people are using a language.