Hacker News new | past | comments | ask | show | jobs | submit login
How to rapidly improve at any programming language (2016) (cbui.dev)
468 points by jcubic 31 days ago | hide | past | favorite | 123 comments

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.

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:


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...

Broken env vars had me frustrated for a few days. I've found finding the right docs in elixir to be difficult because they tend to be fairly terse and assume you know where to put things in your application, if that makes sense. They give you the function call but not explain how to parse its results.

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

Please do.

Yes please. It has been such a pain to deploy.

>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.

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!)

Or just wrap it in a container and pretend that all environments are the same as whatever flavor of Alpine / Debian / Ubuntu that you want it to be.

For Elixir specifically, I found this post from my friend Matt to be a big help when I was deploying my first app. The Phoenix docs section on deployment were also useful.


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.

That part where you have to make a commit in order to attempt to fix a CI problem was driving me nuts. It‘s the same with Travis.

Concourse gets this right - you can run a pipeline task as a one-off from your workstation until it’s done, and only then check it in. And even ssh into the build container in order to debug build failures.

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.

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

> 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.

> 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).

Were you trying to further illustrate the tooling point?

Made multiple contributions to the CairoGraphics project back in the day. Biggest problem? The insane "clever" Makefile structure one of the maintainers had set up. It worked as long as it worked. If it needed to change, one guy alone pretty much was able to tune/change it. It was a language unto itself.

Sorry, I was responding to the “not expressed so much in code I can look at” point. All these things should be expressed in code nowadays. I’m sure some Makefiles are excessively complex - and Terraform and K8s manifests surely as well - but you should hopefully be able to hunt down some good ones.

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.

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

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.

I remember hearing about his MIT Challenge. This answer on Quora from an MIT student highlights some of the issues with that challenge https://www.quora.com/How-do-MIT-students-and-professors-fee...

In the book does he reflect on any of this, or is it based on the MIT challenge at all?

Can be done given that a person has free time, energy, and good planning. It doesn't seem feasible for someone who has adhd or add.

Anecdotal, but I burned through 1/3 of a two semester abstract algebra course in 3ish days of full-time studying, and solving all exercises. But in all honesty, the retention would have been very low had I not began a linear algebra course aimed at graduate pure math students (I am not a math student, nor do I have a math degree).

For such a challenge to work with topics like mathematics, the content needs to be planned such that every course studied builds on top of the previous one, so that the student essentially revises and uses the content studied the previous week.

Maybe that applies to traditional learning environments as well. I graduated years ago and most of what was taught I seldom use and don't remember anymore. I just know they exist, what they're good for and how to refresh my memory if I ever need it.

Have you tried flashcards and spaced repetition? Perhaps these could fix what you perceived as a downside?

I found that for me, the best way to learn anything is to write very extensive notes as if I was teaching the topic, i.e. the Feynman Technique. As I go through the process, I compose a collection of Questions/Exercises to solve and have frequent revisions, in which I draw random exercises and solve them.

By the time of the examination, I have an extensive set of notes that I can search through, and have transitioned to solving the exercises for speed over precision since precision has already been attained. I also transition from solving on paper to solving in my head.

By solving for speed, I mean that after many repetitions the answer that I provide is coarser and distilled because I have good understanding of the finer details, and the finer details can only be attained by writing extensive notes and solving for precision.

In the end of the day though, time is needed to fully absorb the content. The reason is that making structural changes in the brain is very expensive, but spaced repetition and usage of certain pathways make them much more efficient.

In essence, the Feynman Technique is, inho, the best way for a scientist to self-study a topic, and flashcards in various forms along with spaced repetition help achieve that task.

What would you do differently today than the article?

I'll probably go back and update the article at some point.

Background on the book Ultralearning. It was written by Scott Young who went viral for doing his MIT challenge, to teach himself the MIT CS coursework within a small amount of time.

I would expand on the post and focus on the concept of direct learning. That is, if you're not really practicing a skill in the way you're going to use it in an actual real life situation then it's less optimal.

The example he gave in the book and I totally agree with is learning a language. People look to apps like Duolingo where you're working to recall vocabulary and language in a way that's much different than when speaking.

This isn't to take anything away from doing drills wherein you focus on a specific subset of a skill, like say, free throws in basketball.

The approach I discovered myself and outlined in this post is really a drill for doing code reviews in a language you're learning and learning idioms and patterns from the community. People don't usually look at these aspects because usually the advice is to build a project you're passionate about.

I'm bad at finding side projects to build from the ground up that I'm "passionate" about. I have a couple of drills to work on coding more actively than reviewing code. I take an open source library that I'm interested in, take the tests and write the code to make the tests pass. Or vice-versa where you write the tests for a library. You can make this as big or small as you'd like. I'd start with either a function or a module that's interesting.

This way you zero in on the coding aspect and you don't worry too much about designing the interface since it already has tests. It's also much more real world than doing leetcode algorithm problems. I was taking this approach when I was working on learning how the raft consensus protocol worked.

I would not edit the post in any way, leave it as it is. But I would love to read a follow up. You can link to that new post from that old one.

For me your article is a revelation, didn't realized that I can just read old PR to check how to contribute to Open Source project. I've never read this advice in any guide that show how to contribute to FLOSS and I'm working on Open Source for more than 10 years (I'm sometimes read about how to get started, when I was starting with OSS, there were no guides like this).

I would give this advice to anyone that that want to contribute, it's even more important than looking for good-first-issue or help-wanted. This should be first thing the person do when trying to contribute. Look at old PR.

For me learning new language is side effect. You always learn when you're practicing with real project and work with more experienced developers. It doesn't matter if you work on closed source program in your own team at work or on Open Source. But with Open Source there may be more people, and big project are usually created by very smart people.

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.

Can vouch Scott Young's work. It applies to other subjects non-related to programming as well.

Would love to hear more about that. What was your biggest takeaway from Ultralearning?

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.

>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.

Nothing ? Maybe a website that you wanted to exist but there's nothing quite like it ? An app, a game... Its not only about solving problems exactly but about having a vision and wanting to turn it into reality.

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).

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.

How can it be wasted time if you're able to build context and a mental model of the repo? The whole point is to "rapidly improve at any programming language" right? Sure, you're not going to contribute net new code but you'll be primed and ready to contribute in the future while achieving your original goal. Whether or not this works, I don't know. But dismissing it as worthless is kind of a stretch and offensive. But thanks for your opinion.

This guy deliberate practices

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.

I thought about doing this, but the difficulty for me is finding the projects that are going to be optimal for learning the language.

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 :)

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.

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.

Not really for Python, either.

You can definitely read it https://docs.python.org/3/reference/grammar.html Though I found it useful only to answer narrow specific questions.

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.

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.

I have a feeling that most of these skills don't change all that much between languages

Knowing important utility libraries and toolchain of the language is important and it differs significantly between languages.

Doing Leetcode doesn't even teach how to build a 10000 LoC project.

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).

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.

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.

> 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?

Up front, I don't disagree with you, but let me throw out a parallel benefit of your scenario here:

For the most part, in software engineering, a building won't collapse if I'm fucking around with a language and doing sub-optimal things. If I need optimization, I probably know that going in, and would probably take the time to know exactly what language/features I should use.

Since most software built today is pretty low risk/inconsequential if it fails, we might be moving the state of the art forward faster than they might in structural engineering simply because we have the freedom to fuck around and learn. We can test our materials in production, whereas I hope the dude that built my office can't. Like, yeah, definitely don't do this with medical devices and airplanes, but with CRUD app of the day, I might learn something when people decide to use it all of a sudden and it grinds to a halt.

I dunno, I should say I'm not a real software engineer in the first place and am open to being totally wrong here.

we might be moving the state of the art forward faster than they might in structural engineering simply because we have the freedom to fuck around and learn

Thanks-- I think that's a very concise response & reflection on my comment.

I still think we can & should do better, but you're right that the lower stakes probably lower the bar on acceptable crystallization of experience into best practices. Which is problematic because of things like writing a library for your own low-stakes project, but the library gets published on github and used by someone in a something that isn't low stakes.

Maybe part of what we need are defined "stakes" levels and corresponding criteria for acceptable practices at each stage.

> I still think we can & should do better

Totally! And I really like

> Maybe part of what we need are defined "stakes" levels and corresponding criteria for acceptable practices at each stage.

I think I'm going to start testing this with the TPMs and Engineers I work with. I'm going to ask a more senior TPM on my team to think about this and how it should be incorporated into our specs. My hypothesis is our engineers would be happier knowing about the risk profile of whatever failure modes we've id'ed, and they can design accordingly.

That said, I don't really work on high risk software, so this is all relative. Most of our stuff is in the "push the button again" category if it dies.

I think you read this wrong, the performance doesn't matter. It matter that the person learned something new even that he was experienced Clojure developer. And he did this by reading closed PR.

Success Open Source project are usually created by very smart and experienced developers. And big projects have a lot of them. Their Code Reviews are much better then anyone your closed source team will have, unless you're junior developer in team of Senior developers.

Right now I'm thinking that at work we also have git (for intranet application) and we have PR, this may be very good idea for newcomers to read the PR that was done to understand how some features were implemented instead of just diving into recent code. This may be best advice I've seen in a while. But maybe it's just my own idea that came from this article, that you've understand differently.

For me this article is about advice read closed PR you will learn a lot, here for Open Source projects, because OSS projects on GitHub are biggest projects you can find.

I fully agree that there is significant value in what the author writes even if there was more of the sort of crystallization of experience into learning. I just thing that this method of learning-- which seems not just useful but essential in learning how to write performant and less buggy code.

As I said, experiential learning and learning from others will always be important & valuable, as it is in any field. I just think the balance between that and more established best practices is weighted too heavily toward the "figure it out for yourself finding ad hoc sources" side of things.

> 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.

That's an interesting take – I like the idea of a catalog of standard tasks with implementations in several languages as well as their performance characteristics. I suppose Rosetta Code gets the ball rolling with this, but it's missing some performance metrics. It reminds me of Ben Hoyt's piece[1] on counting unique words in the KJV Bible in different languages.

1: https://benhoyt.com/writings/count-words/

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...

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

This is basically what they say in SICP. Write programs. That's it.

It could be small projects or it could be well-known puzzles you already know. Fibonacci- iterative and recursive, fizz buzz, sudoku puzzle solver, 8 queens, etc.

Storytime: I would work at site when I worked in defense and do 15 hour days. I could sit there and monitor, as the job required, but I was also learning Perl for the job. I had no Internet so I spent all my time writing tools and reimplementing every programming puzzle that I could think of in Perl. In very short time I became the go-to "Perl" guy even though all the "toys" I made in spare time were "stupid and useless" according to coworkers.

I did something similar to learn Go & gRPC. I had a python client for displaying a simple COVID-19 report with the option to export as CSV, and had a Go server that sent a request to a public API to collect the data for the report. Did I need gRPC or the Go server? Not really, but when you're learning something new, there's a certain psychological benefit to being able to finish something using the technology you're learning. That, and you can focus more on the learning part instead of getting sidetracked by the other details of a larger project.

> A library to convert celsius to fahrenheit.

I don't think you learn anything with that, unless you mean getting confortable with the toolchain.

You can learn a lot from new technology. Do it with state machine (xstate in my case). Build a restful API. Do it in Nim. Write a gui with Fable.Elmish. Whatever you are learning at the moment. If you want to create a raytracer instead of a degree converter, go for it :)

Instead of using a library for state machines, have you thought about trying a language [1] that does that in a type safe way, with a compiler that has your back if you forget to deal with a state?

[1] https://elm-lang.org

I read a lot of good think about elm. I would personally rely on F# and use Fable (with elmish syntax), but most front-end team are not ready for this kind of jump. xstate is quite easier to insert into a classic React code base. js devs dont really like to move outside js. Beside it is hard to onboard js devs, let's say that the F# or elm pool are even smaller.

Also some issues with Elm like breaking changes, lack of library support, etc, makes it a little awkward for prod

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".

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.

I have a similar problem, only it is with JavaScript. I started using JavaScript in 1997 and have been using it professionally since 1999. I am far more comfortable with JS pre-ES5 and tend to stick with what I know. Very very slowly I have been coming around to more modern JS, but it is very hard. It feels like complexity for the sake of complexity versus the (perhaps perceived) simplicity I have been accustomed to.

I find modern JS much simpler, much more terse. You don't have to carry `this` around like a chain, you have tight arrow/rocket functions, you avoid leaky scope with var and you have mutability control.

It's taken me from "this is a mess" to "ok I can work with this."

It sounds to me like you have a familiarity issue. When something changes drastically in something you're comfortable with it evokes a very strong natural rejection, because it's like someone's taking something away from you.

I agree with you for the most part. They keep adding more and more to the language and it is getting more and more bloated. It's becoming a chore to keep up with, and the added power isn't that necessary. Much of what they add is just making the language more terse. I do prefer the terseness once I get used to a new feature, but having to relearn javascript all the time is pretty annoying.

I really admire small and simple languages that don't change much over time. Lisps, SML, etc.

But once again, many of the improvements are quite nice once you learn them and get used to them. I wouldn't want to give up arrow functions, for example, now that I'm used to them.

Parts of it are overly verbose, but as a 1997 developer you're likely to understand that better. Have a play with a Lisp, or Python's functional aspects, or Haskell, then think about how you'd put those in JavaScript: chances are, you'll end up with a similar solution to what we have today.

Perhaps that is the problem. Other developers came into JS, since that was where the jobs/money was, but wanted JS to be like the languages they left behind. Instead of adding onto JS in a “JS”-way, they pushed to change it to more closely mimic their previous languages. Now JS feels to me like this strange thing is JS at the core with these non-JS things bolted on around the edges. Syntactic sugar, like Class, that makes people coming from OOP languages feel like JS really is an OOP language like they are used to, while under the hood it is the same as always.

What would you or others recommend to fellow dinosaurs wanting to come to grips with modern JS?

The first time I learned it was back in the days when it was mainly for mouse rollovers. I want to tackle it as if it were a different language these days (which in many ways it is). But in years past I've been put off by what seemed like high volatility in the current best practices, to the point of flavor-of-the-month syndrome. I'm sure there must be a stable core that's worth learning and using, but as an outsider I have trouble spotting it.

The 30-40 people wouldn't seem to be in the market for building a small project, could they be simply happy in their jobs? Working with 30-40 C/C++ developers just for browser-oriented code you obviously work at a company of a size where people have families and stuff, settling into a career mode.

OTOH there are plenty of people who do know JavaScript, and dislike it precisely because of that.

i agree. working on your own when learning a language seems like a great way to pick up bad habits, especially if you’re moving paradigms. eg going from c to go probably isn’t that dangerous, but moving from java to ocaml is likely quite dangerous

Have many front ends are actually written in vanilla JS? I thought that in many cases TypeScript is actually used instead.

Perhaps it's a vocal minority or something that is giving this perception. The reality is far more projects are written in javascript than TypeSrcipt. Even greenfield projects.

A lot. TypeScript is becoming popular these days, but there are still a lot more projects being written in JavaScript than TypeScript.

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.

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++?

Well since you asked...a 2D game engine https://github.com/ensisoft/gamestudio

i play guitar every morning in my free time. work is for work. you’re a good enough programmer already. enjoy yourself.

For some coding is a craft and a job. Just as I would expect a professional musician to enjoy growing in their craft and learning from their peers, so do people in other areas of life, including programming.

Do it on company time.

If you enjoy programming for its own sake, why not improve your skills in it both on and off company time?

Depending on workload you will need to watch very carefully for burnout and other mental exhaustion issues if you do this.

Not all of us are professional programmers, and especially not all of us are only professional programmers.

For me, programming for free would be painful at a cellular level.

Better to learn the piano or how to do portrait art.

And my work is not programming so coding in the morning for me is the same as you playing guitar.

Programming constantly changes and evolves. Does your employer allow you to use your work time to read journals and educate yourself on modern developments? If not, you’d better do it in your own time if you want to avoid being stuck in the past.

If your employer doesn't allot some time for you to do just that, ask them to, or find one that will.

You read journals about programming? Like research papers?

Eh, I was a hobbyist before being a pro. I love coding at home, I just won't do the same thing I do at work.

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

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.

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.

> 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.

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.

Nice advice. I always hear people suggest building some projects to learn the language, but I doubt if it's realistic given other constraints in life (I also tried it but the initial excitement wears off pretty quickly). In the end, knowledge can come from anywhere, we just have to find the right source.

I can tell an anecdote from my own life to confirm this theory.

My first PR at nixpkgs, I had to close because I didn't understand what the maintainers were complaining talking about, it was like they were speaking a different language. It was only one month later, after reading other PR reviews, talking on IRC and thinking about all of it, could I make sense of what they wanted from me. Since then I've started doing exactly what the author described: comment on other PRs with things that I was confronted with, and/or saw others be. By now I've gained enough knowledge to come up with own criticisms - indicating that I've learnt quite a lot.

This is precisely why I hate coding, even the articles about coding dont make sense to me.

It's funny cause I feel the opposite way... I read endless amounts of articles that I don't understand, books that go way over my head, and even tutorials about things I'm completely unfamiliar with and somehow it's entertaining? I've started reading The Linux Programming Interface [1], thinking I was well versed, and realized how little I knew about my environment. It's sort of motivating knowing that I'll always be able to dive deeper into the rabbit hole?

One pet peeve I do have is on forums dedicated to help people (i.e. Stackoverflow, Arch forum, etc), albeit a small percentage of users, seem to think that most basic things are "common" knowledge. I understand that we shouldn't handhold and leave people to do little to no work but the attitude certain responses have rub me the wrong way. People ask questions precisely because they are uninformed, why not point them to the documentation or at least in the right direction?

[1] https://man7.org/tlpi/

I hate giraffes, even the articles about giraffes don’t make sense to me

As a first step I like solving basic problems on Exercism (but any other leetcode platform will probably work) and then working my way up to the more advanced ones. Then I like to read a thick, in-depth guide to the features of that language while continuing to work on increasingly harder problems. When I start actually using the language for work or other real-world problems I’ll read through the code of the libraries I’m using.

I’ve used this approach to come in as a lead developer to unfamiliar languages and give meaningful feedback to developers who have worked in that language for 10+ years.

Contributing to open source is, to me, very similar to learning a language at work. The difference is that you seldom have the chance to learn a new language at work because you generally have to first be experienced with it.

To me, I always learn the best when there's a necessity to ship my code. Side projects won't do, and I always revert to using my skills developed at work. Therefore, this sounds like a very good piece of advice to start with.

But don't only a few languages/frameworks/library collections have such a repository of "PR"s, with diffs and review comments and everything?

If it's worth learning right now it will.

First try it yourself. Then read how others did it.

You will improve rapidly.

This is potentially approachable advice for a total noob who can't really code: Just read the pull requests and comments in open source if you want to start learning.

It's thought provoking and not what I expected. I'm used to hearing "If you want to learn, build something." That assumes some basic knowledge I simply don't have, so I haven't yet managed to pull it off.

I just feel that taking on projects I can't [yet] do, is the best way for me to improve.

It bucks up my language skills, design skills, debugging skills, research skills, framework skills, etc.


This only works for so long until the devs get tired of spoonfeeding. More importantly: There shouldn't be subtle nuances in something like a web routing library which is _supposed_ to be trivial. Just the other day I had the experience of watching a grown man give a presentation on his beloved HTTP library, explaining fundamentals of asynchronous (TM) programming and syntax as if the audience does not understand their own programming language in 2021, after seeing the previous 500 LangX.FrameworkY.HTTPlibs. This shouldn't be a thing. We shouldn't be relearning basic shit every day. The problem aside from UNIX being a giant pile of garbage, and HTTP being utterly pointless (can you even name what problem is being solved when you create a new p2p application and make them talk HTTP to each other?), is that everyone keeps making their new languages and libs to "fix" one tiny issue, and they _always_ lack basic knowledge of the past 50 years of PL history, such as Standard ML which is better than whatever they just came up with.

I love this approach. I think looking at the FAQ for a programming language's tag is also an amazing way to dive into a programming language. Lots of detail, different approaches and people discussing best practices on even the simplest of programming tasks.

"start reading them from the beginning. Just a few a morning for warmup while you drink your morning coffee and catch up on email."

How do you read PRs while you catch up on emails?

Not to discount the overall advice, but this statement is kind of weird.

I came up with this trick (reviewing other PRs, after thinking how I would to it) to speed up learning technology at my working place where we don't have enough man power to do mentoring.

This is actually a great idea that I hadn't thought of. I've been trying to learn a new language for something important and it's been a bit much. I'm going to try this.

When I need to learn new language I try to solve basic coding questions with minimum number of characters. You learn a ton about language this way pretty quickly.

"1. Every morning, take your favorite open source library or one from a language you're learning, go to the closed PRs on Github and start reading them from the beginning."

   s/library.*learning/operating system/
   s/on Github//

I've always found that writing lots of code and reading a variety of real world code are the most effective ways to learn new languages.

But I recently discovered coding livestreams, and the good ones are really amazing! It's really eye-opening (and sometimes fun) to watch experts talk through their thinking process, while deciding between language features or primitives, or while picking dependency libraries, observing their tooling and stacks, and watching them test and debug things.

I'm learning Rust right now, which I think is a deep and complex language, and watching these streams have been incredibly useful.

Likely intended as a reply to https://news.ycombinator.com/item?id=28577371

Yes! I have no idea how I botched that!

Moved thither. Thanks!

Being good at anything or anything in demand doesn’t translate into an income.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact