Ask HN: For those programming 10+ years, what do you wish you knew 4 years in?

360 points by dhruvkar ↗ HN
I've been programming for ~3 years now, first just on the side and now full-time. My learning has been in stops and starts. Now I can feel the cumulative learning paying off. I'm also realizing there's SO much more to learn. What advice do you have for programmers just hitting their stride?

537 comments

[ 2.2 ms ] story [ 358 ms ] thread
I wish I knew the Functional Way :)
I second this very much. As pretty everyone says, it changes how you treat code and data. Surprisingly even when they are not the same thing :)
Thirded. Functional Programming should have been at least 4 years into programming, not 10
I wish I had taken the time to understand LISP earlier.
Why?
I was going to say the same thing. Why? For me at least, Lisp is by far the most enjoyable language to program in. Decades of my life spent fighting with class heirarchies and long compile times were all just in vain!
I'm no expert in Lisp, but I'll hazard an answer. Compared to modern languages, Lisp is uncomplicated and follows a small coherent set of principles that allow the writing of code to flow. In contrast, coding with objects is inherently constipated -- so much of the language's state and organization is hidden you don't tend to remember where it's all been tucked away. I find myself unable to employ natural idioms as readily as I can in a non-OOPL, and that interrupts my train of thought.

And IMHO, design patterns make the constipation worse.

I'm not sure what you're talking about. ANSI Lisp has a great object system based on a small, coherent set of principles that allow OOP code to flow ...
Lisp is by far the most powerful programming language out there. In fact, Lisp is not a language, it is more a philosophy:

- If a language's syntax is written using an structure that the language itself can easily manipulate, - in such a way that the source code can generate new source code, using the full power of the language (no restrictions), - in a easy-to-program, straightforward way,

... then you practically have a Lisp language.

As somebody important said: "Lisp is the programmable programming language". This is the key difference among the rest of the languages.

I have spent about 26 years programming and only this year I set myself to grok Common Lisp. The power of Common Lisp, and in particular its object system (CLOS) makes languages like Java seem like ugly toys for miserable people.

I understand that lisp has power but I remain unconvinced that power in any way correlates to writing better programs. A lot of the utility that e.g. static typing provides is a sort of convention of how to write code such that we can then use tools to do the mundane work of verifying that our code is accurate or refactoring it. In other words, lack of power makes code note maintainable.

I don't doubt lisp is fun and easy to write, but power doesn't have much say when it comes to refactoring. That's where convention wins out. How is refactoring 10k lines of lisp?

Refactoring 10K Lisp is very good.

Lisp compilers provide diagnostics about code; it's just those diagnostics aren't the arbiter of whether or not something gets to execute.

Leadership and conflict solving through empathy. Also public speaking.
Learning new things is great but don't be afraid to reach for familiar tools.

Using one or two new things on a project rather than 10 you'll be both more likely to get somewhere, and more likely to pick up the newer elements well.

If you think you are in for the long haul then please buy a standing desk!
and exercise!

no point knowing how to code a web server in 6502 assembler if it hurts every time to sit in front of a computer.

That's just one tool to avoid strain and it's not for everyone.

The important thing is to remember that strain creeps up on you slowly, then hits hard. You can get away with bad habits for years, but left unchecked one day you'll find you can't do anything, it all hurts too much.

Don't push yourself. If you find yourself aching a little, address the problem rather than pushing through it. I know several people that were knocked out of commission for the better part of a year after a few decades of casual neglect.

Discipline: using, creating and sharing (among the team) checklists.
That while C# is probably a better language than Java, the Java ecosystem is so much more innovative and open.
Yeah, I don't buy it. Especially after seeing what they are planning on Build2017.

Also, it's completely open-source.

I was working hard to learn more about the language I was using then.

When I look back at that period, I think I enjoyed what I was doing but in terms of technical knowhow, I wouldn't change much. Of course I know more now than then but I walked a certain path and I enjoyed it. The process was part of being where I am now. So, I think I'm happy with it so far.

What, I would like to have had since then: A good perspective on how the business functions. More empathy.

I've learnt these over time and even in this case, I think learning these was part of life. I don't really feel like "I wish I had the chance to go back and change things". I just feel foolish about some things I did then but I acknowledge that at that time my level of maturity was different from now and even if I had more (relevant) information or ideas, I'd not have been ready to use them.

Finally, I'd say that as long as you tend to reflect on what you do and where you want to go, you'll do fine. Conscious and intentional incremental improvements take you quite far on the long run.

Good luck!

Use strongly typed languages for large projects
Adding my corollary, if you must use dynamically typed languages - ensure at any cost that you split it up into multiple small independent codebases.
And use type hints whenever possible.
Note that a language can be dynamically typed and strongly typed at the same time. An example of this is Python.

Another example is the latest release of C++, which is strongly typed but now allows for dynamic typing with the 'auto' keyword.

Thanks for clarifying. :)

I assumed that my parent really meant to write statically typed, not strongly typed.

- Don't stress about code coverage metrics.

- Don't use the next big thing before actually understanding the benefits only because someone else tells you to. (Looking at you, Angular and Docker!)

- Stay away from programmers who have strong opinions about certain things. Most of them can't back them up with skill.

- Don't use the next big thing before actually understanding the benefits only because someone else tells you to. (Looking at you, Angular and Docker!)

I'm curious, what do you not like about Docker?

I followed the call of an employee with 10yrs more experience than I have and he proposed we move our infrastructure towards docker containers for easier deployment / management.

Generally containerization of our app was a good step at this point, but we made the mistake to also put redis / postgresql into docker, which obviously is an stupid idea if you're trying to scale things. On top of that, docker networking was a science on itself, and we didn't use any proper automation tools.

Docker containers kept running out of disk space / memory and it took a lot of effort to figure out where to place apps. In the end we ended up in the same situation as before, that some containers were on dedicated machines and the rest had a kind of hard limit on the max. # of instances per machine.

Our deployment process went from taking 2 minutes to ~10-15 minutes because of docker registry and extensive jenkins build scripts. It also needed lots of network bandwith to be transferred to the actual hosts. We had to regularly remove unused images because the docker registry or our docker hosts ran out of disk space.

Finally we changed our deployment process to incorporate docker hub because it was advertised as the premium docker building service. We paid for that service, but it took between 20 and 40 minutes to build our images. This was unacceptable for our use case because we needed to fix bugs near-instantly. Customer support from docker the company and their unresponsiveness towards our latency problems was another problem.

After the engineer in question left towards a very well-known european music streaming startup, we finally ditched docker and moved everything to AWS beanstalk. It does proper version management, config management, auto scaling and can be defined with a simple json file and some some straightforward cli tools.

I'm really not the biggest fan of docker, but it seems like everything y'all did was wrong: improper image caching, so you wouldn't have to continually build the same base images for your services; putting databases in the container, instead of somewhere else; not using cgroups/docker fundamentals to restrict space on the container level; storing state (something) on disk within a container.
You're right, there was a lot of PEBKAC involved. But it was not very straightforward to do the right thing in that situation.

The engineer in question was very excited about the technology, so we went with it. In the end it was a great learning on many levels, and I can really appreciate the kind of problems that AWS solves for you.

Thank you for the thorough reply!
:)

It was a nice exercise to put our struggles w/ docker into a coherent point.

Most companies seem to prefer folks who have a broad base of general computing knowledge plus one specific area of expertise. This is sometimes called a "T-shaped programmer". There are definitely exceptions, but is a good place to start.

Other than that, practice, practice, practice. And get out of your comfort zone when you practice, don't just do things that are easy for you. You are only learning when it is hard and it makes you wonder if you might be stupid.

That almost every job you get will highly prize pragmatism and general problem solving skills over pure technical know-how
...except in the interview.
That nobody cares which language/stack/libs you use as long as it works.
Maintainable and readable is I would say even more important than whether it works or not. If something works and is not readable it can cause more problems than it solves. Because it'll wind up in use somewhere.
- Keep it simple, stupid. Advanced is not a compliment.

- Languages and frameworks don't matter. There's a closed set of concepts they're all reusing. Especially if it's hot shit: that means someone mined ideas from 30 years ago.

- Most problems tend to fall not to cleverness, but to compute power and the right glue. See previous two points.

- Everything is a tradeoff, everything is a moving target. Programming is about the battles you choose.

I like this. No bullshit. Straight to the point. Solid advice.
I'm more or less on the same boat. My advise is, don't let it overwhelm you, learn as the need arises (or you have a burning interest in something). At work I've done a handful of languages (web development can do that quite quickly these days) and I've not been here a year. On my own time I experiment with D and Rust, and maybe soon Kotlin. Those are my languages of interest, I don't do something every single day for hours on end, but now and then I open up an editor and play around with one of those till I find something to build on my spare time. Chances are as you get new jobs you'll learn new languages and stacks, so don't be overwhelmed. How many co workers do you see doing 50 projects in 50 different languages and stacks all at once? ;)
More respect for testing on larger teams. Code regressions cost teams I've worked on 1000's of hours of debugging.
Don't be a snowflake.

If everyone are using X, don't go with just Y because it is slightly more elegant or efficient.

That shipping stable software that works and meets requirements is what people really want. In other words, what the non-tech business people want, or your customers want, is software that fixes their problems, makes their lives easier or makes them more money.

It's easy for us programmers to become fixated on using a newer JS framework, a slightly tighter Java loop or the latest cool language. Took me a few years to realise that even though I care a lot about those things, other people do not. They are interested in the outcomes, not how it got built.

I'm running my own business and building things for myself these days. I use vannilla JS on the front-end and Java 8 on the back. Since I gave up chasing the new cool tech I have built a bunch of stable systems that have been great, well received, products.

If you become someone who has a history of shipping things that work, you will do a lot better than someone who knows how to write hello world in every JS framework.

This. Make your _business_ case, not a technical case. This applies to software engineering, security engineering, etc.

The above comment does not absolve you from doing cool things, it's just that the cool things should align with business interests. No yak shaving. Sometimes writing a one-off script will take 30 minutes, and doing it by hand will take 10. Do it by hand.

This! and know why you are building what you are building.
Here's my problem.

I'm not particularly prolific, so the number of ideas I have far outweighs my execution so far. This is mostly due to ADHD and other issues which I'm working on fixing, and while contextually relevant is not my point.

This lack of prolific-ness means that I have a literal tower (it's rather intimidating) of wanting to build cute but objectively not so useful routines simply for the sake of building them.

I realize this is essentially the foundation of creativity, but I have a hard time justifying doing these things as I take a very long time to execute anything.

So, the ideas file themselves away - and surface when I'm trying to design actual things I'd like to build. And I get horribly distracted with doing X or Y a certain way, or I get carried away with how I can build Z out like this or that idea I had two years ago...

My problem is focus, I think, and mental partitioning, which I'm not good at. Does anyone have any suggestions for how I can do that?

Your "problem" sounds different the one I currently deal with.

My current solution is to have a backlog and spending time to prioritize them. I'd focus on my top priority, and continue writing down new ideas as they come into my mind. When I finish with the top priority, I re-evaluate to find out where the recent ideas fit in. I'd also look into reading about the agile methodology.

If you're like me, ideas come in very frequently. Embrace your creativity and ambitions by logging them. But try and shift your mindset to thinking about what is actually necessary for the final product.

Also, "freeze" your "features" at versioned levels for each project.

If you want to add or alter something, that would be a new project.

Otherwise, you will never finish a project.

Like the work you deliver to your boss or client, there is a Final Product.

And yes, Agile is the best, because it's of the mindset that the Product is iterative!

Your completely right, and it's something only someone with ADHD can understand. Depending on how bad your ADHD is, mental partitioning will be incredibly difficult thing to do and that has everything do with lack of attention/focus regulation.

You will have to find a way to develop the capabilities of your brain(working memory, long term memory, task execution and completion, focus and accuracy). You will have to do something that you have been evolved to do which is to have a creative outlet (Dancing, Music, Art) to develop those abilities. There has to be a task where you have infinite focus/hyperfocus, that builds a higher ability. In a sense you don't have to do something that is hard, but something that comes natural and something that grows.

The sequence of steps and motions that are required for dance, movement of muscles to precisely line up with the notes of a song, to reproduce the form of a drawing/painting all require some sort of mental partitioning. These things are all interrelated. I personally have only scratched the surface, because things become infinitely complex I have to decide what is the most important develop. If your lucky enough to be creative and logical these abilities will bleed into each other.

Personally written organization helps me. I like to use Trello to organize my thoughts. When you get an idea, write a quick note to get it out of your head so you can stop thinking about it. It's written down, you now have the freedom to let go and attend to it later. Schedule specific time to look at that list and put it on your Calendar so you don't forget. "I don't need to think about that right now, I made time on Sunday afternoon to prioritize and pick out which ideas are worth it." or "I will only check my ideas for things to refactor when I have a lull in my schedule, but I'm busy right now."

Also on the tower of ideas-- it's not a to-do list, you don't have to commit to every idea that flies through your head. Your ideas are a great resource for you to reach for any time you need it. A lake of ideas you only need to go fishing in when you happen to want to.

ADHD sucks. I have it, too, and I somewhat solved this problem by moving into R&D, where they pay you for ideas directly. But these fields are rare (quant finance is one of them).
I also have ADHD which has reached debilitating levels at times. Noise cancelling headphones, removal of computer games, and being disciplined has helped. In all seriousness though, it's a more complex condition than most people realize and seeing a specialist is never a bad idea.
I printed this XKCD specifically to remind myself that some things aren't worth automating!

https://xkcd.com/1205/

On the other hand, sometimes you're automating for reasons other than time savings. Maybe reproducibility or auditability.

Or the fact that the task is so mundane/boring/annoying/irritating (pick an applicable adjective) that it's worth it to you to spend a day automating it so you never have to do it again.
The problem with that is if you make a mistake the first time, then redo it by hand, you have used up 20 minutes. Made a second mistake, and you are even with automating it.
I strongly agree.

However, there are special cases where you are exposed to a new technology which enables new outcomes.

I was fortunate enough to blunder into using the Web in '92 and Java in early '95 and they were tools where the "how" did matter quite a lot...

[NB I haven't touched Java in a dozen years or so]

Also there are differences in further employment perspectives.

I mean if you have a problem to solve and you have a choice to use some old tech that you already know, but it is going out fashion, and some new one, then the choice of the newer one improves your employability in the future. For example, I guess in 2000 there was not that much people with 5 years of experience of using Java in production, but those who had it, had to have pretty good chances to easily find decent job.

Of course there is a risk to bet on wrong technology, but at least you keep learning instead of just using ageing tools and becoming more and more disconnected from the current state of the art. It can be as scary as this https://news.ycombinator.com/item?id=11886753, a story of a guy who successfully solved business problems and delivered products with jQuery for a long time and then eventually found that he was out of demand because businesses started looking for people with experience of using React and he didn't have it.

That is true and can be a problem when recruiters just keyword match technologies from your CV.

When I've recruited I've always tried to assess the candidate on ability to get things done rather than knowing a specific framework. I'd look at how deep their knowledge goes and see if they can ship stuff - if they've been using jQuery but I need React then I'm not too fussed if they've shipped quality products using jQuery and have taken the time to learn pretty deeply how it works, the keenness to learn and ability to build things should easily translate to React and I'd rather have this person that someone who has skimmed the top of React for a few Hello Worlds.

I would hope and prey that interviewers would take a similar approach, if they are just ticking off keywords from your CV then it's a pain.

(comment deleted)
I find it funny that you felt the need to distance yourself from Java.
Are you using a java framework on the backend? Something like Spring maybe? I'm just curious, I've been thinking about using Java for the backend of my own projects.
I have used Spring before and I like it quite a bit. I have tended to use vanilla Servlets for most of my projects recently and use libraries like Gson, Apache Commons, PdfBox etc etc where appropriate.

I think if anyone wants to go down the route of using Spring, Play or similar then you MUST spend the time learning it in pretty deep detail. I've seen so many people with "Spring experience" on their CV who can make a webpage appear using the tech but as soon as something goes wrong or they are asked to do something a little different they are screwed as they don't know the framework well enough.

I only use vanilla Servlets and my own stuff because I have been building up my own libraries and ways of doing things over time and I've been burnt enough times with old-school frameworks (like JSF and Seam) that just add so much unnecessary work and ball-ache.

I like to write the fewest lines of code possible and also use the fewest dependencies possible. I find that plain ol' Servlets gives me that for most of the stuff I do.

I appreciate the reply, thanks!

Perhaps I will try to use vanilla servlets for one of my personal projects. I'll have to start reading the docs!

I have to agree with parent heavily and I used to be a long time Spring advocate since version 1.0.

The thing you will find using Java for a long time at any company is you eventually end up with your own framework / stack.... Yeah sure there is some underlying DI or Web framework but a majority of it becomes your framework and workarounds/plugins/extensions for whatever DI/Framework you choose.

I used to to think this was a terrible thing but these days I think using less dependencies, autoconfigure magic, and even using older technologies such as the Servlet API are just easier to maintain, understand, debug, stable and surprisingly easier to train new folks on.

> The thing you will find using Java for a long time at any company is you eventually end up with your own framework / stack.... Yeah sure there is some underlying DI or Web framework but a majority of it becomes your framework and workarounds/plugins/extensions for whatever DI/Framework you choose.

This doesn't match my experience at all. Only really ossified organizations get to this state, even in Java-land. The amount of abstraction I have needed to put on top of Dropwizard in order to do literally everything I've ever needed, from websockets to web pages to file service. The underlying Jersey and HK2 system is simple, well-documented, and straightforward when I've needed to extend it, but these extensions are restricted in scope and easily testable to boot.

I see no benefit, in 2017, to using servlets directly. It's certainly not going to be easier to teach a new hire through look-at-the-code or look-at-our-minimal-doc instead of pointing them at the existing documentation and examples of best-in-breed tooling.

I think you may have misunderstood me a little.

I'm not saying go use the Servlet API directly all the time but you damn well should know it since almost all the others build on top of it (including most of Jersey).

Particularly Servlet Filters. It seems like every framework has their own take on onion processing a request but servlet filters are actually easier to write then say some Spring framework "Advise".

As for Dropwizard... You do know its built on top of all the new JEE stuff like JAX-RS. I am willing to wager it will die and be replaced with something else... but those underlying javax specification stuff (like JAX-RS, servlet api, etc) are still going to be around.

You should know those underlying standard APIs.

The funny thing about you mentioning Dropwizard is it basically started as someones else stack built by mixing standard libraries.... something companies do all the time.

> I see no benefit, in 2017, to using servlets directly. It's certainly not going to be easier to teach a new hire through look-at-the-code or look-at-our-minimal-doc instead of pointing them at the existing documentation and examples of best-in-breed tooling.

Until shit breaks, or doesn't fit your exact requirements or the project dies, etc, etc, etc and believe me it does happen in which case you will need to know the lower level stuff. But yeah don't reinvent the wheel.

> "Until shit breaks, or doesn't fit your exact requirements or the project dies, etc, etc, etc and believe me it does happen in which case you will need to know the lower level stuff. But yeah don't reinvent the wheel."

This.

I wouldn't suggest this sort of self-damage; I've been there and I've made the mistakes. Servlets, as written, are lousy abstractions for HTTP. Worse, where the abstraction breaks to expose HTTP to you, it doesn't really do much in the way of enabling you to do anything you couldn't before.

If you want to use the JVM, one: use Kotlin over Java, it is a strict superset and a better development experience across the board. Two: evaluate something like Dropwizard (or even Spring Boot) well before you go near servlets. JAX-RS is not perfect, but it's a lot better than whatever you will home-roll. (Again, been there.)

It took you 10 years to understand this?
What application server do you use for the backend? Tomcat?
This is why I always ask what is the business value of doing cool thing X on a project.

Using your words if "using a newer JS framework, a slightly tighter Java loop or the latest cool language." doesn't improve the business value of what the customer is getting out of the product, it gets a very big NO.

I became very much against "cv building driven programming".

Along those lines I'm always surprised at how many SUCCESSFUL tech companies even today are built with PHP. Tech stack is often not the driver of success or failure in a company.
Besides, PHP is a mature and very well working technology. Not shiny, but otherwise very good.
There's a balance to be struck there, though, and pejoratively referring to the seeking out of ways to improve as "CV driven programming" probably isn't the healthiest attitude out there. If you're not doing new things, you run a very great risk of sitting in a weak local maximum. Don't fix what isn't broken--but you need to be stretching out, too. Not doing so induces a sense of stagnation to a team and can chase off developers with ambition (which you can and should harness) and a sense of quality.
I agree there is a balance to be met.

For greenfield applications, chose whatever the customer ask for on their Request For Proposals, or suggest modern solutions if they leave it open to proposal reply.

On existing solutions, deployed for several years on the field, actually measure what it brings in regarding business value. Either in terms of reducing project costs thus improving profit, or improving customer UI/UX thus improving the value the customers get out of the product, specially if it helps them to improve their profits.

What I am against is just adopting tech that doesn't improve anything, sometimes even causes products to be abandoned or removed from the market, just for the benefit of a few devs improving their CVs.

I have taken part in a couple of projects where it actually happened. Architects were busy chasing the new shinny instead of delivering what customers actually cared about. In the end the product was canned.

> What I am against is just adopting tech that doesn't improve anything

How do you know what improves what if you don't use it in anger?

Pilot projects, technology analysis, market research, reports from external consulting companies, architecture assessments, university projects,....

There are many ways to research new tech without touching the current product development.

Sometimes it is better to be the turtle than the rabbit.

There are plenty of cases where new frameworks come out that allow you to move forward much more rapidly as a dev team. They allow better testing, better code organization, etc.

Especially in the Javascript world, it's such a new field that new techniques are being invented regularly. I've seen old backbone applications that are essentially frozen in time feature wise, because the code is so cumbersome and coupled together (by the framework's design) that it becomes impossible to add new features without having to refactor/rewrite the entire thing.

I agree, if you have have a finished product that won't be getting many new features at all, then leave it alone. But if it is an ever evolving product with new use-cases and features being dreamed up regularly, that application should probably be re-written many times over.

On JavaScript world, old techniques and architecture lessons are being rediscovered every day. There is hardly any invention going on besides JIT compilation improvements for dynamic languages.

As for CV driven programming, here is a real case from a long gone project.

Dumping a fully working and battle tested Perl scripts for application installation in several flavours of UNIX, for Groovy based ones built on top of Grails.

It really improved the business value of those customers having to deploy a JVM, executing scripts slower than before and what was a simple set of CLI commands turned into starting Grails and navigate via web pages uploading files.

I agree completely with this post but want to provide some additional insight that I've gained:

Learn to enjoy your work as that's the only way you'll make it long term. If that means spending a little extra time to write an efficient algorithm or structure your code efficiently v.s. just "getting it done", then do so for your mental health, not for the company.

You see, we're craftsman at the end of the day. We all want to feel like we are contributing quality work, and often that conflicts with the business's priorities. Take pride in your work and you will find it easier to show up at the desk each day.

“A reminder that the goal of a given computer program is first of all to meet some business requirement may come across as a platitude. In practice, the excitement of technological challenges often slowly causes attention to drift from the end to the means…”

—Stephane Faroult, “The Art of SQL”

Before becoming a professional programmer, be sure you understand that programming for recreation and for money are two completely different things, otherwise the latter has a big potential to take all the joy out of the former.
(comment deleted)
* Functional is generally better but don't be crazy about it.

* Have tests but don't be crazy about it.

* Keep your development process as streamlined as possible.

* New languages generally aren't as hard as you might think and they might be the right tool.

* The right tool for the right job can make a huge difference.

I would have upvoted you if it wasn't for your last sentence which is the most hyped in our industry. WRT this sometime ago I wrote this in a S.E. answer:

I'm a hater of the sentence "use the right tool for the job". Nowadays, any language can do pretty much anything you want to do with it (except if the language has recently been created and is still in the early stages, e.g.: Elm?).

So then IMO these days what you have to do to choose your programming language is not ask what you're going to do, but know what you want to avoid.

So I use this rule of thumb:

    Do I want to avoid paying licenses (or resorting to piracy if I'm in the early days of a startup and I don't want to spend money), then I choose a language and a set of tools which have open source implementations (compiler and class libraries) (i.e.: C++11 vs MS Managed C++)
    Do I want to avoid chasing memory leaks for the rest of my life? Yes, therefore I use a language which has garbage collection (i.e. Java vs C).
    Do I want to avoid painful evolution of my project, especially when it's getting larger (wrt easy refactoring and maintainability)? Then I use a statically typed language instead of a dynamically typed one (i.e. TypeScript vs JavaScript).
    Do I want to avoid recent headaches I've had with other software projects in which concurrency was very hard (read: race conditions), then I choose a functional language (to achieve immutability, avoid side-effects, etc.) (i.e: F# vs C#).
And it's not that I ran out of questions, there are many more...

But, did you guess it? The questions above are the most important ones you should ask yourself when choosing the next language to use/learn, in my opinion. And, did you guess it? This is why my current favorite programming language is F#: because you can avoid most of the pitfalls that you find in other programming languages in the industry, and you still can do pretty much anything with it.

Cool :)

I use Python for anything related to text processing or webscraping. I use Haxe for when I'm doing cross platform game programming. I use React for web UI / front end work. Erlang for distributed stuff. In each of those cases I've tried other tools and the ones I prefer now seem much more effective ...

I've never done anything in F#

You can do text processing and webscraping easily with F#. React is a framework, not a language (you can still use React with F# if you transpile it to Javascript). You can do cross platform game programming in F# too. And distributed programming of course.
That it's not a competition on writing dense code.

People tend to not say what they really want. Become good at finding the actual requirements. As a CS student, if there are requirements engineering courses, do take them.

For many projects implementation is the least important part of the project.

Professional conduct is worth a lot.

I wish I had learned to keep my head down and code without the expectation to release. Because nothing I released in the first 4 years of programming professionally was good, at least not by my standards today. Try telling me that 6 years ago.

I was dead set on building entire products, it's why I loved programming. It was why I love lego. But in hindsight it would have been a better use of my time to work on smaller projects and ideas. As almost nothing ever got finished before I was working on something new. I have very little in terms of a tangible outcome from that time period, and it extended beyond those first 4 years.

Now I wouldn't want to work on a full product before I knew I had all the larger parts finished first. I wouldn't want to work on those larger parts before I knew I had the smaller parts those larger parts depend on first.

Programming with this mindset has provided me not only with endless work to do. But less stressful, more satisfying, easily digestible work with semi regular tangible outcomes.

If you're any good, and confident in your abilities, you can go contracting for the (comparatively) big bucks without needing over a decade's experience.

Most people are not that good, or confident, even among higher earners.