Skip to content

Learning how to write software

There's this common perspective among novice developers that some languages are "hard." I think this perspective is overblown and taught to impressionable folks early. There are bad languages for sure, but the difficulty of a problem exists whether you deal with it up front or at runtime.

How people learn

People learn best with immediate feedback.

When you're learning to walk, you have a lot of senses thundering information into your brain while you shoot out signals trying to imitate the others around you. You generally figure it out pretty quickly, considering the complexity of what you're doing.

I recently drove a trackhoe for the first time in my life. I thought those things looked so difficult to operate and the people who figured them out are geniuses. Turns out, those machines have continuous, analog input and immediate feedback. I was picking and placing small logs in under 10 minutes. I wasn't lighting matches or opening pop cans, but I had functional dexterity in minutes. I am not special.

I want to learn faster

Functional dexterity, or baseline competence, is achieved by trial and failure. The quicker we can try, fail, and try again, the quicker we can achieve that competence.

When writing software, the first touch point with the software is when you're writing it. Kind of tautological. Anyway, your IDE (fancy text editor) will often point out problems with what you're doing as you do it. That's great for learning.

The next touch point is where languages diverge: Some let you run from the text, and some have a text post-processor, called a compiler.

On text runnables

When you run from text, you are actually compiling while you run. This lets you write hopeless code that can never work, and even run that code. You do not get immediate feedback on your errors. You get stack traces if you're lucky, and then you're having to imagine the state of the machine at the point of failure and work out how something could have caused this or that to be null, or whatever the error is.

Running from text is great for experts who are writing scripts. It's not that great as a tool for teaching people how to write software.

On compiled runnables

When you run from a compiled artifact, more things are typically checked before the program runs. Compiling is usually pretty quick, and often you have a tool that will compile on save, which gives you something very close to immediate feedback.

Some compiled languages, like java, kotlin, c#, go, c++, c, and typescript, don't bother checking all that much. Checking things like nullity, uniqueness, semantic safety, choice in error handling, and disposal of resources is tough; so not many do that stuff up front. They let you crash like a text runnable language.

They give you the worst parts of text languages, and the worst parts of compiled languages.

Some, like C and C++, still have reason to exist. Others...

A language for learning

Rust is a compiled language, but it checks a long list of error categories on its way to compiling. When you write something that violates a rule, the compiler tells you immediately where the rule was violated, and it often both explains and offers a way to fix it. It gives you immediate feedback, like a trackhoe or like learning to walk.

It is criticized for borrowing being complex, but shared state is complex. Either you can sort out the complexity up front with named rules and instant feedback and help, or you can edit, run, try, crash, interpret, repeat until you're pretty sure you won't crash anymore. Sure, the latter works, but the former works better.

By providing names and rules, and a framework for safe procedural software's shape, rust teaches more than how to write software: It teaches you how to think about software consistently. You will write better code in every other language after learning to think from rust.