How to learn Computer Programming

Probably in a better way

Computer programming is one of the things that make you feel like a creator, you create algorithms that imply data structures, relationships, interaction, basically anything that involves data, an abstract construct that carries information. Being a computer programmer makes you the master of your data. It lets you take a break from our conflict-filled, merciless world in favor of the logical, perfect, digital realm. Programming implies creativity, ambition, curiosity, and most importantly, fun, empowering your freedom of doing amazing things.

But how does one become the master of their own logical world?

I am going to share my on-going experience and some observations that I made along the way.

Some background

I have always been fascinated by computers, big boxes filled with electronics that eat electricity and produce data. When I was a young(er) boy I was carelessly fiddling around with the control panel in Windows XP, trying to uncover every function of the operating system, and then reading more about them on the internet. It was clearly some kind of magic, and I wanted to master it.

I decided to study hard and go to a computer science-oriented high school, that also had middle school classes, in fifth grade. There, I joined the CS computer club hosted by Cristian Frâncu where I started learning serious stuff basically from scratch.

Beginning programming

The basis of programming is computational thinking. To think “computationally”, you must develop your abstract thinking (the abstraction component of computational thinking) to be able to create algorithms, an ordered sequence of rules that the computer executes. Programming implies elaborating an algorithm and implementing it for the machine.

In fifth grade, we first learned basic algorithms and represented them with flowcharts. One example is an algorithm that determines whether an integer is a palindrome or not.

palindrome flowchart

Credit: Cristian Frâncu. Licensed under GNU FDL

Instead of beginning programming with some simple programming language like Python, we were beginning with algorithms. And that’s the moment I realized that’s the right thing to do.

Another important thing that everyone should learn when starting learning how to program is structured programming. I can’t emphasis this enough, it is a game-changer. Basically don’t use goto or break instructions unless absolutely necessary.

For example, let’s write a simple array search. We’re trying to find an element e in the array arr.

int arr[4] = {1, 2, 3, 4};
int e = 2;
for (int i = 0; i < 4; i++) {
    if (arr[i] == e) {
        printf("found x\n");
        break;
    }
}

At a first glance, it does what it should: it prints “found x” if x is a member of arr. But the algorithm itself sounds broken.

The algorithm should be the following:

  1. Take each element of arr
  2. If the element equals e, print “found x”

What the code above actually does:

  1. Take each element of arr
  2. If the element equals e, print “found x”
  3. Abort the search.

A better, structured programming code is the following:

int i = 0;
while (i < 4 && v[i] != e)
    i++;
if (i < 4)
    printf("found x\n");

Moving on with actual programming

After “mastering” flowcharts, it was time to learn a real programming language. And we (at the CS club), as fresh programming learners, started with C.

And let me tell you why C is the best programming language for beginners. Not Python, not Ruby, not Scratch (god forbid), but C.

C is very simple, and pretty close to the metal. Not as close to the metal as assembly, yet still not as high-level as Python. It is the perfect middle ground for programming learners, because it forces you to write efficient, from-scratch code. And it has a pretty strict type system.

In C you have to define the data type for each and every variable and array you use. There is no such thing as iterators, you have to keep an index and iterate manually through the array. It doesn’t have any kinds of shortcuts, which is good for first-time programmers.

You’re constantly reminded that computer programming is serious stuff and you must treat it like so. You can’t leave unused variables scattered in the code or forget to indent your code. You’re making an ass out of yourself. Ignorance is the worst thing that destroys the world, let alone programming. If you don’t have a high enough degree self respect, or a high enough degree of respect for programming, then you’re wasting your time. Either exercise your self respect, or just give up on programming, it’s a waste of time if you lack the necessary dedication.

We exercised programming by solving computer science problems on sites like codeforces, csacademy, timus and varena (varena is available only in Romanian). These problems are short tasks that have very tight memory and time constraints, forcing the solver to think each data structure, algorithm and variable declaration carefully. Example problem.

Over the years I learned many algorithms, like select sort, quicksort, breadth-first search and many more. There are many online resources for learning these, such as The Topcoder Forum.

Further reading: Introduction to Algorithms by Cristian Frâncu, CS101 - Introduction to Computing Principles by Stanford University.

Also, make sure to participate in online CS contests held by Codeforces and CSAcademy!

Drifting to real-world programming

The main difference between competitive programming (solving problems) and real-word programming is that you have much more constraints than time and memory and that usually you don’t make only the solution, you also make the problem, and you generally have more freedom in the whole project. It’s a whole new world.

To get started, you need to make projects, lots of them, like a simple snake clone with text-based graphics, or a text-based adventure, a web application, anything!

This is the step that requires the most dedication. It is one of the hardest steps in the process of learning computer programming.

Trying new things

Diversity, in good measure, is very good for you in general, not just for programming. Experiment with new programming languages, learn how to make web apps, fiddle with micro-controllers like the Arduino.

I first started by reading Head First Java, that’s when I learned about object-oriented programming, the first real programming paradigm that I’ve learned. It was mind blowing, so structured, so hierarchical, it has changed my way of thinking. Although the Java programming language is well-known as an ugly language and platform, the underlying concepts are very useful for a programmer.

In one summer vacation I tried to make a video game using the amazing LibGDX game development library. I discovered eventually that game dev is not for me, mostly because it implies making art assets. Still, the math involved with it is very useful.

And Java’s ugliness convinced me to learn Ruby and eventually Ruby on Rails. My dad gave me this neat idea to make a simple online educational platform where students can read lessons and submit homework. Each student was assigned a class, and each class had a set of lessons. It was for my mom, she is a teacher. And I started writing that thing using Ruby on Rails. My knowledge of Rails was null at the moment, I learned it as I progressed.

And I learned about the Model-view-controller pattern, SQL databases, templates (for the views), HTML, CSS etcetera. One important observation I’ve made is that all those components that make up a system must be separated. You can’t just mix up the views with the controllers. They are all separate things that interact with each other. Breaking up big components into smaller components is very important when working with computers.

The point is, never stop exploring. Curiosity is a very important trait for anyone who wants to excel in the field.

Communities

It’s always a good idea to find people who are interested in the same things as you. You can share opinions, help each others and learn. When talking about computer programming, the biggest communities can always be found on the web.

The ground-breaking moment as a young programmer was when I discovered one of the biggest online community of people: Reddit and a couple of subreddits that I found to be interesting: /r/programming, /r/learnprogramming (very useful resource), /r/linux, /r/polandball, /r/listentothis and many others.

However, it is always better to always have friends around you, whom you can talk face-to-face about programming. Being in a CS-oriented school for 4 years certainly helped me find such people, although many of them continued with competitive programming (which is very sad in my opinion). My boy Ciprian Ionescu is probably my only friend who fully understands me when I’m talking about programming stuff, and I can’t stress it enough, you need such people in your life.

Unix and ricing

I had this neat idea of installing Linux in dual-boot on my laptop. And the first Linux distro that I installed on my laptop was Arch Linux because the best way to learn something (in this case Linux) for me is the hard way, as described by master z3bra. Make sure to read the article, it’s very good.

So I downloaded the ISO, booted it up, and followed the installation guide. I went all or nothing. Without prior experience. That was going to be FUN. Ten minutes later, it booted. Afterwards I created a user, installed some essentials programs like Firefox and the X server and continued the journey of learning Linux blindfolded.

Now, time for some back-story. Two weeks before I begun my Linux journey I discovered /r/unixporn (not NSFW, I promise!). It’s a subreddit dedicated to desktop customization on Unix-like platforms (usually Linux). And it was Unix for a reason. Many posts that hit the frontpage at that time featured tiling window managers. Instead of running a full-fledged desktop environment like GNOME or KDE, users were using lightweight programs called “window managers” that have the job of, well, managing windows: resizing them, listening to their requests (and fulfilling them), grouping them by workspaces and others. Every window manager has its bells and whistles, the most popular on unixporn being i3. i3 is a tiling window manager, meaning that instead of just putting windows on the screen, windows in i3 always take as much space as possible on the screen, like tiles of different sizes on a wall. It it lightweight, easy to use and has a simple configuration file syntax.

Back to my Linux experience, instead of installing a familiar desktop environment to begin with, I just installed i3 and configured it to suit some of my needs. It all felt spectacular, I was in charge of every aspect of the operating system I was using.

Afterwards I tried to “rice” my system. It was looking magnificent “back then” (2015), but now I think that it looks absolutely horrible. Here is a recent screenshot.

And I went down the rabbit hole. This is the time when the dedication and curiosity traits for programming are being put to good use.

I ended up writing pretty much my own mini desktop environment by gluing together scripts and little programs. For example I made a status bar script that uses lemonbar to display the current time, date, currently playing song, speaker volume and workspaces. This is the script in its current state.

And that’s the moment I realized how beautiful the Unix philosophy is. A decades-old philosophy that say that programs should do one thing and do it well and communicate to each other through the simple channel of text and pipes, encouraging composition. And that’s exactly what I was doing with the bar script. It was pulling information as text from programs like amixer that provides sound device information, processed it with other small programs like grep and sed and finally gave it to lemonbar.

It was a symphony of programs. Many performers (programs) making up a musical masterpiece, following the instructions of the music paper, coordinated by the conductor. Truly beautiful.

Remember when I said something about breaking big pieces of code into smaller pieces? The Unix philosophy is exactly that, taken to the next level.

The Nixers

Around the time I was fiddling with scripts on my Linux desktop I discovered a great community of people who had the same passion for Unix as I did: Nixers. And they have an IRC channel for talking stuff about Unix!

I chipped in, talked to many great people (they should be listed on my resources page) about Unix, programming, desktop customization, philosophy… Learning things is always easier with friends!

Two members of nixers, z3bra and dcat wrote a great set of small programs names wmutils. One program prints the ID of the currently focused window, another one moves a window… You can figure out that they are only very simple programs with very simple jobs that can be combined in an infinity of possibilities.

Using these programs I ditched the window manager I was using at that time in favor of a set of scripts based on wmutils that together made up a simple window manager. My shell-script based desktop environment was almost fully script-based. I eventually extended it and added a notification system and other stuff, inspired by z3bra’s post “Pop it up!”. But the whole hacked around window manager was so simple, it lacked a ton of useful features, like multi-display support. It was limited to only one display.

I wrote a set of small programs in wmutils-esque fashion called disputils. I modified some parts of the shell glue window manager and it eventually had multi-display support.

But what about protocols like EWMH that define for example how a window should request to be maximized (for example when you double click the Youtube player)? It was clearly not in the X11 spec, and wmutils had absolutely no support for it.

It was clearly the time for something more complex.

The big project

I’ve already told you to make a lot of software projects, big and small, to practice the art of programming.

Eventually you will end up starting you first big project. I followed the hard way and made my very own window manager. I named it windowchef.

These are the steps I followed in order to make something:

Know your target

So I was going to write a window manager. What should be the goals of the project? I settled upon these goals:

The “remote-control” goal has come advantages. The user can configure keyboard shortcuts for moving the windows by using a program like shxkd that executes commands for certain configured shortcuts, while also making it possible for external programs to interact with the window manager, thus adhering to the Unix philosophy.

Start small

After having some goals in mind, I started implementing something simple. First, I made a program that is barely considered a window manager, letting the X server to do most of the work. My program could spawn terminal windows under the mouse pointer and focus the windows under the pointer. swm’s source code by dcat helped me a lot.

Moving on

One window manager that is pretty close in goals to mine is 2bwm. I started studying its source code and implemented the basic stuff in mine (a window manager requires quite a lot of boilerplate code). I soon had a working prototype that could draw borders and move and resize windows with commands from the client. I implemented a very simple client that can only send commands without receiving answers, inspired by this post about vain’s katriawm.

In a couple of weeks windowchef was done.

Open source

I’m writing this article because I want to help people to learn from my experiences and eventually I will learn from their experiences. This is why people have blogs, to share their experiences and findings.

I love the open-source community. It’s one of the best things that has ever happened to software in general. I always open source all my programs to let people study and learn from my programs. Sometimes people send patches / pull requests, it makes me really happy!

I really, really encourage everyone to use and contribute to open-source projects. You’re helping everyone, especially yourself.

My first real steps into opensource were when I published a silly web app called “Albumify”. It lets people make imgur-like picture albums, entirely client-side. And it looked horrible:

The Old Albumify

And I advertised this silly project on /r/unixporn…

The next day I woke up with this:

My first pull request

I was stoked!!! Someone actually liked my work and decided to improve it! This is how the web site looked after some “minor” changes by Dylan:

The new albumify

It was entirely different. Of course, to return the favor, I contributed to his big project, neofetch. I was his first contributor!

Now, windowchef actually gained traction. As of today it has 116 stars on GitHub, it actually has users! It is also included in the software repositories of Void Linux. One of the beauties of opensource is that people can come with all sorts of pull requests. Some of them were pretty big, like this one that implements cardinal focus. You can tell the WM to focus the first window in a given direction.

So you shouldn’t just opensource your code to make it easier to study, you should also make it opensource for a confidence boost ;)

Real-life projects

When you feel that you’re ready, you should pull the trigger and make that dream project of yours come to life. I started the XMC Project together with Ciprian. It will be a very flexible CS problem platform and contest manager kinda like Codeforces based on microservices. I have already implemented the authentication and authorization server, based on OAuth2. It feels real. And so it will be.

Sadly I don’t have any experience in the development industry, I’m currently in 9th grade.

So in conclusion, to learn programming:

  1. Be in the correct mindset. Be curious, ambitious, dedicate yourself to the arts of computer programming.
  2. Start with the basics: algorithms. Learn C, be close to the algorithms and the machine.
  3. Solve harder problems, learn data structures.
  4. Make your own software projects. Lots of them, anything that comes in your mind.
  5. Learn new technologies, programming languages, design patterns, while making your own projects.
  6. Be in charge of your personal machine. Use Linux, customize your desktop experience.
  7. Join programming communities. Meet new people. Learn with them! Join online forums!
  8. Share your projects, opensource anything. If you made something you’re truly proud of, post about it on reddit, Hacker News, forums. Make yourself known. If you don’t stand out nobody will approach you.
  9. Be open to criticism and software contributions. Contribute to other projects, criticise others!
  10. Always keep learning.

Thank you for reading, have a nice day! If you’re interested, you can find all my software projects on my GitHub.