top | item 28577371

How to rapidly improve at any programming language (2016)

468 points| jcubic | 4 years ago |cbui.dev | reply

123 comments

order
[+] travisgriggs|4 years ago|reply
This seems great for language/library knowledge. As an experienced polyglot, the languages are not where I'm hitting the wall these days though. It's the tooling. I can learn new language basics faster than I can figure out the ecosystem/tooling.

For example, my current conundrum is how to deploy an Elixir Phoenix/MQTT app. Writing the app was a fun curve to climb. And I could use techniques like described here to learn from others in the actual programming. But how to build an executable I can wrap in a systemd process running on a different machine? Those are actions people do, not expressed so much in code I can look at. The few blogs I can find on the subject are mired in deep CI toolchains.

I want the blog that discusses the secret sauce to learn to acquire the knowledge to work the raft of ever evolving tools we have to work with now days. The "materials" (the languages) are the easy part now days. It's the massively automated complicated machinery we've built around the language of ideas that are my personal pain point of entry.

[+] rubyn00bie|4 years ago|reply
I totally agree with you about tooling being the major hurdle, and I would like to also note your particular case: deploying Elixir/Erlang the first-time is a real motherfucker.

I've deployed (server-side) code in Ruby, Python, PHP, Java, .NET, JavaScript, and probably a couple others I forgot about... but among all of those Erlang/Elixir was by far the most difficult first-time deploy (as an OTP application). It has gotten infinitely better, but probably only for those of us who have been doing it for a while (6+ years doing Elixir professionally for me). For your particular case, let me see if I can help you out ('cuz I've definitely been there).

It now mostly boils down to, use mix release:

https://hexdocs.pm/mix/1.12/Mix.Tasks.Release.html#module-te...

with the "secret sauce" being to setup a build server where you will build the production release. You'll want the same flavor/version of Linux you plan on deploying to, and then copy the build artifact (tarball) from your build server to your application server (or somewhere else in-between).

One other thing to note, there's a good chance (because everyone does this) that you'll have some broken environment variables, or module attributes, because you thought they were set at runtime but they are in-fact set at compile time.

Maybe I should write that blog you're looking for...

[+] Barrin92|4 years ago|reply
>But how to build an executable I can wrap in a systemd process running on a different machine?

by far the most frustrating thing when I started out programming learning python was the point at which I'd made something I wanted to show my friends and I got to the 'How do I produce a standalone executable' point.

Not only an issue with advanced deployment, even for very mainstream languages the tooling story is still often not great. When I taught a CS intro class in uni this kind of stuff dominated student questions.

[+] derefr|4 years ago|reply
The trick for tooling is usually to find the blog post where the newest major version of the tooling was announced. Such a blog post will almost always contain a demonstration of what idiomatic use of the tooling looks like now. (Because, if it didn’t, how would anyone get started using it?)

This is also the domain of the more extensive language tutorials and/or “Learn X” books. Elixir’s website’s getting-started docs have a very good section on using Mix, for example, including `mix release`.

(People tend to forget to re-check an ecosystem’s official getting-started docs as new tools are introduced into the ecosystem. I’d encourage everyone to give your favourite language’s docs a quick skim every year or two; something new might jump out at you!)

[+] technion|4 years ago|reply
This was my "learn Rust" project: https://github.com/technion/open_safety

The time I've spent on the Github actions is substantively higher than the time I've spent on the .rs files. Of course you can't "test actions before commit" in the way you can actual code, so I kept having to make branches, make 15 commits like "try action fix again", followed by squashing them all down and merging.

[+] gmathews|4 years ago|reply
As someone who codes stuff by myself a lot and needs to pick up tools I've noticed a lot of the knowledge feels like it might come through oral tradition. Handed from developer to developer. Places have learned which way through the tools cause the least problems and will have an informal community of practice around tools - where you can just quickly ask someone something that may have seemed too trivial to the tool creator to put in the docs.
[+] wilsonfiifi|4 years ago|reply
One approach that has worked for me so far is:

1) find out if the runtime/framework is supported but Heroku or if there are any buildpacks available.

2) spin up a Dokku instance using Vagrant for local development and testing

3) deploy to a live Dokku server

If/when I encounter any issues I add Heroku or Dokku to my search query and 9 times out of 10 I’ll find an answer to my issue. Else I just dig into the Dokku docs and GitHub issues and figure it out.

So for instance googling for deploying a Phoenix app with Dokku results in a few hits such as this one [0].

There's also a lovely UI for Dokku being actively developed: Ledokku [1]

The only drawback currently is when you want to horizontally scale your deployment. You can use their kubernetes or nomad schedulers but I think those are an overkill in terms of complexity. You could also use a load balancer in front of multiple Dokku instances but you then lose the ease of deployment, configuration, etc…

Which is why I think their docker swarm scheduler [2] will be one of the most important feature they could add. It’s currently on the roadmap but I’m sure with a bit of sponsorship and a few pull/merge requests it will become a reality.

[0] https://nithinbekal.com/posts/dokku-phoenix-deploy/

[1] https://github.com/ledokku/ledokku

[2] https://github.com/dokku/dokku/projects/1#card-59170273

[+] samhwr|4 years ago|reply
> But how to build an executable I can wrap in a systemd process running on a different machine? Those are actions people do, not expressed so much in code I can look at.

The former sounds like a makefile, and the latter sounds like a Terraform plan (perhaps combined with something like Kubernetes manifests, but that’s getting more architecture-specific). These days I don’t think there’s any excuse to use the point-and-click approach for setting up infrastructure: it’s effortful, bug-prone, a security hazard, means everyone has to be trained in yet another area, and risks accidentally spending far more money than you intend (either by using surprisingly expensive services like Spanner, or by inadvertently leaving unused infrastructure running).

That said, I do agree that platforms like AWS are unnecessarily complex for the vast majority of CRUD web developers. The complexity makes sense for the small percentage of people who are genuinely setting up a very idiosyncratic and unique architecture, but the 98% of CRUD developers really need an opinionated platform, perhaps built on top of AWS/GCP/Azure and modelled on v1 platforms like Heroku, which would set up the infrastructure you need for the average web backend.

[+] jcubic|4 years ago|reply
If you find some project that do this right and use tools you need, just ask the author to publish his knowledge. It will be beneficial to everyone not only you. Most people like to share their knowledge, and if you find that other person, just try to find another one.

A year ago I've read article about the person that self-published a book (printed and ebook), here wrote an article how he do that and how he created it in markdown (very well written book about TypeScript in Polish), I've asked an year ago (when read that article) if can publish the code, he said that he was thinking about this. Recently he published how own blog system online on GitHub and wrote another article this time with link to GitHub. I still waiting for the book code.

[+] lenkite|4 years ago|reply
Hit it in a nutshell. I find C++ great as a language - complex but wonderfully powerful. It's like wielding a sharp [DragonSword]. However, the tooling is in the stone age compared to Rust. And there doesn't seem much cross-vendor interest in improving matters. The committee sticks to the language and not the broader ecosystem.

This makes it a no-go for younger programmers who are spoilt by friendly tooling - great build systems, package managers, superb documentation tool compared to the ancient, decrepit dinosaur that is doxygen, etc

[+] 147|4 years ago|reply
Hey, author here. Surprised to see this on the front page of HN since I wrote it 5 years ago.

I've always been fascinated with talent acquisition and skill development and would probably different recommendations today after having more experience and reading Ultralearning by Scott Young.

[+] ryohkyo|4 years ago|reply
What would you do differently today than the article?
[+] jcubic|4 years ago|reply
I've published this because I was reading your more recent post (GitHub Actions Limitations and Gotchas), found in newsletter Programmer Weekly, and found this post that was 10x more interesting.
[+] 5faulker|4 years ago|reply
Can vouch Scott Young's work. It applies to other subjects non-related to programming as well.
[+] mbrevoort|4 years ago|reply
Would love to hear more about that. What was your biggest takeaway from Ultralearning?
[+] rafaelvasco|4 years ago|reply
Two things I did and always do: Code things that solve real problems you want to solve. The harder the problem, the better you'll get in the language and as a programmer in general.

Second, look at existing open source, well written code that, again, solves a problem you're interested in. I always emphasize this: Things you're passionate about. That way you can master any language/framework. By master here, I mean you can code anything you want in the technology efficiently. Your final app will be: Easy to modify/enhance, easy to understand in terms of code. Memory and CPU efficient in terms of runtime.

[+] nonima|4 years ago|reply
>Code things that solve real problems you want to solve.

Everyone says that but I can't think of any real problems I personally have that I could solve using programming.

[+] _skhan_|4 years ago|reply
I feel like the approach the author laid out near the end is passive and would lead to one assuming they have retained some knowledge. At the most, it would help someone avoid a similar bug/mistake.

A better approach would be to checkout the repo at a commit before the fix and try to replicate the solution in a short amount of time. You would then build context around what the contributor had to figure out and in the worst case you'll have a "gold standard" solution to fallback on (assuming the PR was successful).

[+] jcubic|4 years ago|reply
I don't think it's good idea, because it will be wasted time. You can use your time to contribute to the project after reading some closed PR, try to use your knowledge to contribute.

For me it's best advice how to start with Open Source, and be sure that your PR will be accepted. And as side effect you will learn a lot, but this is with any practice like with your idea, but you will make project better. Your idea is as worthless as doing LettCode or similar.

[+] raman162|4 years ago|reply
I never thought about reviewing existing open source project PRs to get better at a language. It seems so obvious considering it's similar to how I get ramped up with new projects.

> 2. When you want to level up, start reading the diff, and review the code and changes yourself before reading the comments.

> 3. Finally, when you start feeling more confident, start leaving those comments on new PRs so that the maintainer doesn’t have to. You’re starting to contribute to open source!

The steps from two to three are pretty dramatic, I personally would replace step 3 with tackling an open issue related to code you reviewed before. I feel like to give feedback on a PR you need to be intimately familiar with the code, something you get from writing and/or making changes to it.

[+] wyclif|4 years ago|reply
I thought about doing this, but the difficulty for me is finding the projects that are going to be optimal for learning the language.
[+] zarzavat|4 years ago|reply
My hack to improve at a new programming language is to read its grammar. We instinctively try to learn programming languages the same way as we would a natural language, bottom up. But unlike natural languages, programming languages have complete grammars that can be read in a session. This will prime you with the right questions to ask ("WTF is an XYZ?").

Doesn't work for Clojure though :)

[+] dgb23|4 years ago|reply
For Clojure what helped me was starting to read the source. Typically core lib first and then the Java implementation of certain constructs.

For me it helps tremendously to see how the sausage is made.

[+] toomanydoubts|4 years ago|reply
Not sure if this is what you're talking about, but there's https://learnxinyminutes.com. It's really awesome when getting started with a new language. If you're an experienced programmer, you can get to a newbie-but-ready-to-write-some-code level after a 15 minute reading on a new language.
[+] wrycoder|4 years ago|reply
Not really for Python, either.
[+] darkbatman|4 years ago|reply
If someone need my suggestion, here is what you do - try doing different sort of questions (multiple topics too) on leetcode from different topics may be just 20-30 in language you want to learn.

Its different way but you will learn a lot of new libraries, ways to mutate objects, lists, all sort of data structures and new things really really fast.

[+] nostrademons|4 years ago|reply
Leetcode is leetcode. It's its own skillset within software engineering, one you often need to get a job, but it bears pretty little resemblance to any of the skills you need to deliver working, functional software that solves a user's problem. Practicing it will help you get better at it, which may help you land a job where you can practice all the other skills, but don't confuse leetcode with proficiency in software development.

Among other differences, leetcode teaches you little about reading large unfamiliar codebases; debugging; organizing large software-engineering projects; working in teams; teasing out actual requirements; making incremental progress; real-world performance (and the tools you need to identify bottlenecks); and most of the libraries and frameworks that are common industry knowledge.

[+] xondono|4 years ago|reply
I’ve tried a lot of those, even contributed to exercism. I think it has it’s uses, but you can only extract value from those exercises once you know enough about a language.

For me those exercises are more about developing muscle memory than really learning a language.

OPs idea is good, but I think fails in the same way. I don’t think you’ll get much value out of reading PRs until you have certain familiarity. No amount of PRs will teach you what a monad is, you need to dive deep and conceptually understand the model(at least IMO).

[+] raman162|4 years ago|reply
I've only done a few leet code questions but only in languages that I'm comfortable with. Even then, I've had similar experiences to the author mentions where I've gotten different perspective on how to approach certain problems.
[+] ineedasername|4 years ago|reply
I learned that using the collection functions on strings in Clojure is much less performant... But it doesn’t have to be my PR. It can be anybody’s."

This reveals a fundamental problem in coding. Best practices for performant code shouldn't require ad hoc digging into PR's, and as long as it does then we'll have code that is buggy & slow(er than necessary).

Learning from others, in any field, will always be a valuable source of improvement, but it just doesn't seem that, in software dev, it results in laying down solid incremental increases in general knowledge that makes its way back into the education of future devs or current devs in a language new to them:

If this was structural engineering, you'd have to have taken a "materials" course and learn all about different types of materials, their properties, load capacities, degradation profiles and how to evaluate new ones that come your way under the same criteria.

Maybe that's what we need for software development. A structural engineer wouldn't use a composite material without knowing its performance characteristics. Why should a programmer use something like string collection from a language without knowing its performance characteristics?

This is on us to demand this, to standardize-- not languages themselves-- but the performance profiles & characteristics that we must know about in order to make a choice on which tool to use. And it shouldn't be that each user has to figure it out on their own, dig into PR's or whatever. Again, there will always be experiential learning. But too much is experiential right now.

[+] rob74|4 years ago|reply
In the spirit of this, the Go project has a "common code review comments" document (https://github.com/golang/go/wiki/CodeReviewComments) - topics that come up frequently when reviewing pull requests. Reading these can certainly help you get better at writing (idiomatic) Go...
[+] aloisdg|4 years ago|reply
My own take, to improve at any programming language, use them to build actual small project. The smaller the better. Something familiar. Something easy. A library to convert celsius to fahrenheit. A webapp to count the day until Halloween. This kind of useless-ish stuff.

My last example is to add a state machine with xstate to a project fetching some data and formatting a nice output. Do I need a state machine? Not really, but it is a good way to learn it. btw, the goal of the project is to smooth attribution to stack overflow's answer. I just started it, sorry for any bug.

the app: https://stacktribution.vercel.app/

the code: https://github.com/aloisdg/Stacktribution

[+] greggman3|4 years ago|reply
A lot of people seem to be saying "build a small project" and I'm not saying that doesn't work but...., but, something I've experienced a lot is that people stick to their old ways, myself included.

As a C/C++ programmer I used to hate JavaScript (pre ES5). I didn't like it's function based scoping system. I didn't like it's prototype based class system. I loathed using it and wrote as little as possible, only enough to make a small WebGL demo or add a tiny feature to my blog. I was basically trying to use JavaScript as C/C++ and hating it.

At some point though I flipped. I actually started using JavaScript and playing to its features. I embraced prototypical inheritance and all the ways it's more flexible than class based. I embraced JavaScript's dynamic typing using, where appropriate, the ability to easy wrap APIs, to write more generic and flexible code. I also really loved closures and building functions that closed over data, something that, at the time, C/C++ didn't have.

I also really enjoyed that, at least in the browser, JavaScript is bundled with a lot of CROSS PLATFORM functionality (graphics, GPU access, audio, video, networking, UI) that pretty much no other language has and of course that I could share anything I made with just a link.

Then ES5 to current shipped with better scoping, import, map/reduce, promises, async/await

But, I bring this up because I still work with 30-40 people that, even in 2021, they work on the browser teams (Chromium, WebKit, Firefox) and yet none of them really know JavaScript. They all still have the same attitude that I had 15yrs ago. They avoid it as much as possible and they treat it like C/C++. Some of them have been doing this for 15+ years. They've written 1000s of even 10s of 1000s of lines of JavaScript to create tests for the features they're implementing but they still having really "learned the language".

[+] ecshafer|4 years ago|reply
I come from a C++/C/Java background and also always disliked Javascript. It still has its warts sure, but the book "Javascript the Good Parts" really opened my eyes. I liked programming lisp in school quite a bit, and the idea of just treat Javascript like a lisp and program it in this specific way was really enlightening. Prior to that I was either shoe horning it in to a java model, or building on some legacy JS that didn't really have a methodology to it.
[+] enduku|4 years ago|reply
In addition to wonderful responses already posted, I'd like to add one more: Learn Forth. Learn Lisp. Learn APL. No need to be good at these; just enough to learn their programming models. Imperative, functional, OOP, or any other, it doesn't matter. Learning the programming model in such languages changes the way you think. Then start with a language you wish to master. Start with a problem in mind. Always have a problem in mind. Try coding the thought on paper. Do the same with the target programming language. Though it appears as an idealistic procedure, it does serve its purpose and instills confidence in the learner like no other approach out there.
[+] bradneuberg|4 years ago|reply
Does anyone know good open source projects that are using modern c++ (c++ 11 to 17 techniques) that I can study and possibly contribute to to get better at c++?
[+] jamisteven|4 years ago|reply
This is precisely why I hate coding, even the articles about coding dont make sense to me.
[+] eyelidlessness|4 years ago|reply
The is a great suggestion. I’ve also learned a lot just from reading the already-merged code of projects I’m interested in, and stepping through git history to see how it evolved. I even frequently do this on my phone when I want time away from the desk.

For instance I’ve been super interested in SolidJS[1] for months. I learned from reading the source that a lot of the work is done by its underlying dom-expressions[2] compiler. And in reading its source, I learned enough about JS AST transformation that, when I had a need to do some AST transforms of my own for work, I knew enough to confidently timebox a proof of concept to two hours (and actually finished the work in that time!). All from reading code casually on my phone.

Sure, I front-loaded a lot of that work in my free time. But I did it because I was genuinely interested in the project I was learning from.

1: https://www.solidjs.com/ 2: https://github.com/ryansolid/dom-expressions

[+] lordnacho|4 years ago|reply
Here's what I do when learning a new language. I've written projects in C#, VB6, C++, Python, Rust, Kotlin, Java, Swift, Objective-C and a tiny bit of typescript.

- First of all, find out what the typical toolchain is. What IDE do people tend to use? What compiler? How is package management done? These can be really complicated or super simple to answer.

- Compile a Hello World and see that it runs. If it's reasonably specific and supported by a bigcorp, there's often extensive downloadable examples. Android and iOS for instance will tell you a lot in their tutorials. If there's a book, get the book and see how the author presents it, just skim it for key concepts, don't get bogged down in the cpp templates SFINAE explanation, it will only make sense once you have done some coding.

- Find out how modules work in your language. Every language has this, and you need to know it before you can get anywhere, both reading and writing.

- Note down keywords from the tutorial code. Recurring things you see, look them up. If you're doing Rust maybe you see `match, await, clone, some, and unwrap` quite often. If it's iOS maybe `controller`, or if it's Android maybe `fragment`. Google all these things.

- Look for the libs that you need. If you need a websocket, look for that. Major frameworks will tend to have good examples in idiomatic style. You can't know all the libs you'll need, so just get the ones that are obvious. This will give you a better histogram of keywords and soon key concepts.

- Start to code your actual thing you want to make. As you run into issues the errors will give you keywords. This will improve your knowledge as you google those as well. After a short time you will run into larger issues than syntax, and those issues will turn out to have been mentioned in the appropriate books.

[+] adamnemecek|4 years ago|reply
Also reading the source code for the standard library can be illuminating.

Note that some languages have pretty subpar standard libraries. This might have changed but ~10 years ago the Ruby standard library really left some things to be desired. I don't recall the details but I wasn't a fan of parts of it.

On the other hand, the Rust standard library is top notch.

[+] einpoklum|4 years ago|reply
> Also reading the source code for the standard library can be illuminating.

That's a lot more hit-and-miss. On one end of the spectrum, you have Java, where all of the lower-level, nitty-gritty work happens within the JVM anyway; and on the other end of the spectrum you have C++, where it's "turtles all the way down" almost, with lots of repetitiveness, ugly hacks to within the library to help the user avoid ugly hacks in their code, a big bunch of preprocessor macro definition checks for meeting innumerable compatibility requirements for different versions of the language standard on different platforms, and so on. Yes, you will learn from it, but it will be painful.

[+] journey_16162|4 years ago|reply
For me working with different languages and seeing different codebases helped a lot.

I have always been a solo dev, I have some 6 years of experience, including 3 years getting paid for it. However, up until 1 year ago, I knew only PHP and JavaScript - and I did not know about many good practices in either language - i.e. I did not even use a linting plugin, I was sloppy with git commits.

Then one year ago I picked TypeScript for a long-term personal project. TypeScript is now my main language.

- I was still working in PHP ocassionally (to get paid) - after using TypeScript and Eslint, I decided I at least need to use some linter in PHP. The linter had a very useful rule I did not not have in Eslint, rule that said: "This looks like commented out code". Thanks to this, my new TypeScript project is now not polluted with commented out comments all over the place. I'm not sure if I would have picked it up if not for this small detour.

- I was used to describing what every function does, even if it was obvious just from the name of it. This is because it's a very common practice in some PHP projects - I presume this is probably because of lack of the type system, you have to use PHP doc to comment function parameters, and if you comment function parameters, you may want to add the description of the function anyway. Thankfully I took some detour, I wanted to learn a bit of C++. I looked at some codebases, particularly Chromium - and I was surprised to see how little comments it had, compared to say, WordPress (PHP). I immediately knew this is the right approach for me. I started dropping any obvious comments and not repeating myself and instead name variables / functions to be more descriptive.

- I also looked a bit into Rust and saw how the language is using return results rather than exceptions. I compared both approaches and decided that it would be better if I used return results rather than exception, as Typescript has no way to annotate that a function throws and what it throws.