If you have the option then the country is not your primary concern. The quality of your PhD experience is 95% determined by the quality of your supervisor and lab-mates. So you should judge based on that irrespective of the country. How much attention can they give you, how successful have previous students been, etc?
Absolutely right. Go tour your potential lab and take the grad students out for drinks, without any professors present. Get them to give you the real story: is the professor sane and emotionally stable? Is the work environment supportive? How do graduates from the lab do, do they get good jobs and academic appointments?
First thing is you need to actually be a good engineer. No point optimising if you suck, just put your head down and learn.
Next thing you need to know is the rules of the game in YOUR organisation. Every company is different and the rules are different. Google is unique, so at other companies the game is very different.
Then you need to move the needle on whatever matters. That might be improving metrics, that might mean becoming drinking buddies with the right people, it might be purposefully going to work for a failing team so you can be given the chance to take it over and prove yourself.
You are correct about the tech industry here (low salaries relative to US) but developers working in finance in London make comparable money to Bay Area tech firms.
People routinely get paid £100k straight out of university to write code in London, just not in the tech scene. Total comp in the financial sector with 5 years experience is commonly £200k.
Which is not 'ludicrous' but more than you might imagine from seeing £40k job postings in the web dev sector.
That is so no true in my experience as someone working in finance in London. Can you name 1-2 companies paying 100k for graduates or 200k after 5 years?
That's not true as such. £100k with no experience is very hard to achieve, even with long-term comp. Maybe if you work at an algo trading company and get paid by the performance of your algorithms. But then it's more like being self-employed (they just provide seed money and some basic salary).
Total comp of £200k/year is clearly possible but also just on the investment side (not writing software for support systems) and usually involves some risk (i.e. income is volatile). Finance easily pays 2x that of tech in London but only because tech doesn't pay very well. A lot of startups pay programmers not more than you'd get with any other office job which is clearly not comparable with the US.
Here's a great idea: bitcoin settlement, custody, and clearing for institutional investors. There is a huge first mover advantage to be had signing up to prime broker every hedge fund's bitcoins and help settle OTC transactions. I know people who need this. Good luck.
Some things to avoid early on so you can get a working app out quickly:
1. Don't build OO abstractions, just use structs as data and operate on it with free functions.
2. Don't be afraid of long argument lists with lots of references, where the last one is possibly mutable, C-style
3. If something needs e.g. 2 different structs as inputs and mutates a third one, make it a free function, don't impl it on any of the structs.
4. Don't overdo it trying to use the functional idioms for options and results like and_then or_else etc. Just use match and eventually it will be obvious where those fit.
5. Don't worry too much about error handling, just use expect and explicit panics
6. Don't implement your own data structures, compose the std lib ones
7. Get good at using match and enums to represent state and transitions
Once you've got some more experience and you want to try to write more elegant code, you will run into ownership issues.
1. Use guard types. Basically a struct that owns a pointer into some larger data. Write a lot of these with useful utilities for manipulating that data
2. Use guard types for mutating data as well. I tend to have a type which is a big bag of data (often carefully laid out in memory for performance), and then separate types whose only purpose is to contain references to e.g. 2 or 3 different pieces of data that need to be simultaneously used. That type allows you to do whatever that operation is. This saves a lot of borrow checker fighting.
3. Think in a data centric way. What data do you need? What operations need to be performed? Then design your ownership hierarchy such that that can happen.
Finally you will run into frustration structuring large projects.
1. Use cargo workspaces. Isolate self contained chunks of functionality into crates.
2. Implement stdlib traits like Iterator, From, Into
3. You can use associated types to do statically checked dependency injection. In combination with default trait implementations it's a decent way.
4. Use free functions liberally inside modules, but export mostly traits, data structs, and operation structs.
5. Use rustdoc comments in your code and refer to them.
A lot of the above is opinion and might not work for everyone. I submit that it's "a path" of many for getting productive quickly and then scaling up to writing larger systems.
Think in a data centric way. What data do you need? What operations need to be performed? Then design your ownership hierarchy such that that can happen.
I think this is key and still something I am trying to fully embrace
I've come to the conclusion that watching the market is a fool's errand. We don't need to discuss our trades all the time. Or politics. Or gossip. The common space should be used sparingly.
It is more fun though, to have a constant debate. Just not productive.