Carmack is usually great to listen to, by the way; check out some of his interviews or talks if you haven't before.
Carmack is usually great to listen to, by the way; check out some of his interviews or talks if you haven't before.
1. Learning (fundamental) stuff deeply is the way to become great.
2. But knowing how stuff works fundamentally at an abstract level (e.g. being able to write your own toy OS) is not directly economically useful (and/or very time consuming to get to that stage). So it won't get you a job.
3. So for starters learn just one thing that people actually use (say git) deeply at a concrete level. That is economically useful, because most devs will only have fairly superficial git skills, so you becoming the go-to person for git will provide economic value to the company.
4. At the same time, this is an effective way to bootstrap a more abstract deep understanding. E.g. if you really master git, you will also learn a fair amount of abstract concepts that go beyond the concrete tool (deep understanding of git implies the ability to implement at least a toy version yourself, which will teach you useful stuff; in particular if you can implement your own version of git you are probably already better than 90% of programmers).
5. Be mindful that you will be blinkered at this stage (because you only know a single thing and thus lack a basis for comparison), so don't become opinionated yet.
I think this a great early career strategy as long as you pick the right thing to deep-dive into. E.g. if you picked AspectJ or Agent Learning or CASE tools or the semantic web around 15-20 years ago (at the peak of their hype-cycle), this possibly wouldn't have worked out so hot. In particular, learning some things like Spring or Freudian Psychology will probably harm rather than help your intellectual development.
Making a good pick is hard if you lack experience; I'd say if in doubt pick something really everyone in your line of work uses but most people have not mastered and where there is value in mastery (and you can see how mastery might tie into things you want to learn more about at a fundamental level). Also, preferably pick something that has been around for at least 5 years (unless you are quite confident in your nose for trends).
The only down side is there are often reasons those gaps are there, but it's just time to roll up your sleeves and get to work. It's an approach I've taken every time I've joined a team and it worked well for me.
From my experience a lot of those gaps are essentially integration efforts between two systems where one person builds something independent of the other that were supposed to be integrated or are now desired to be integrated yet were never planned or designed appropriately to integrate. In the end, you end up needing to become a master of the disjoint pieces that formed that gap to connect them and have to deal with two 'masters' as opposed to one.
My suggestion is to find gaps that aren't integration efforts, if possible, that are instead extension efforts. This allows you freedom of creativity for some greenfield development while avoiding a bunch of legacy code and technical debt that will swallow you whole. It also gives you a starting leap from something developed by a master to work from.
I can't count how many times I've joined different teams to assist and found a pile of integration efforts (my sample may be biased, YMMV). This seems to be a more common modern phenomenon where people need to pump out something to look good/productive and then coast away before the challenging effort of making things work together occurs. I would say this issue is exacerbated by the mass adoption of "agile" where integration is always an afterthought since business leaders are often the dictators.
Yes! This can go even further and the technical integration work can easily slip into soft/people/team/project/management integration. Here is a talk which warns against doing this kind of glue work too early in your career:
Video: https://www.youtube.com/watch?v=KClAPipnKqw
Summary article: https://noidea.dog/glue
I explain this same concept to people at less software savvy businesses frequently, so it's nice to have an external reference to point to. Going to borrow her nomenclature.
For me it is the latter over the former. I would love to do a 3 point business feature every sprint and spend the rest of the time cleaning up code. Between the POs pushing work onto my plate, as well as everything else I have to do (releases, code reviews, fixing regressions etc.), cleaning up old code is a luxury at the moment.
I also find it quite interesting that you mentioned git specifically, because I’ve been going back and forth for the last few days with myself about whether I should spend the rest of Winter Break and next semester (I’m an undergrad with one semester left) learning git internals deeply. So, this felt somewhat validating of the perspective that I should learn about git more deeply so I can have enhanced practical knowledge, which could translate into more economic value for the company I’m working with after graduation.
Once a decision is made in this regard, I then have to figure out the best way to actually learn it. I’ve considered trying to follow the mailing list[0] and contribute code to the git project, thinking that would force me to learn it very deeply. But at the same time, I feel like trying to go that deep might have diminishing returns and might stress me out. I like the idea of being an open source contributor to such a huge project and gaining more experience that way, but I also worry about the potentially high time cost.
I imagine I could alternatively read the Pro Git Book[1], the git documentation[2], and/or some other specific git internals resource someone has curated, but I haven’t decided what would be best yet.
[0]: https://git.wiki.kernel.org/index.php/GitCommunity
For less of a time commitment, Git from the inside out [2] is a really nice explanation of the internals, from initializing a repo and the files that creates in the .git directory, all the way to pulling from and pushing to remotes.
[0]: https://wyag.thb.lt/
[1]: https://news.ycombinator.com/item?id=19386141
[2]: https://maryrosecook.com/blog/post/git-from-the-inside-out
I know from (my albeit limited development) experience that I definitely retain concepts I’ve encountered via a hands-on approach better, but I hadn’t made the leap to _this_ sort of hands-on approach! I’d just resigned myself to the long slog of trying to get a commit merged into the master branch haha.
Once again, thank you! I’m going to check out both of those resources!
Without getting sidetracked about the merits of the technical interview, it is current a fact of life. In my experience most undergrads struggle solving even the most basic problems and even if they come up with a solution, they are unable to code it in any language of their choice. If you are coming out of university as a "git expert" and can't code up a basic solution, you will get passed over every time.
Most teams (at least in my experience) are not struggling to solve git problems (although they certainly pop up). So while you could add some "value" there, overall you aren't adding a whole lot of value. On the other hand, if you know your language and are a moderately competent coder, you can add a lot more value.
Ive managed to not have to do a technical interview for all of my internships and jobs so far, largely due to my efforts networking and focusing on learning popular technologies (especially React). Ive done the theoretical coursework and enjoy the problems, but the hour-a-day leetcode would not have been nearly as useful as learning a popular library and building connections.
And that said, I'd say git problems are the norm especially with newer devs. Having that one person on the team who is a git-master is invaluable when you've made a mess.
It sounds from your post like you may do front-end work. I work primarily on distributed systems for machine learning, so I can't speak to front-end work, but in my experience understanding basic data structures and algorithms is quite useful in day-to-day work. It is great you have gotten to where you are without doing technical interviews. On the other hand, every job interview I have had has had multiple rounds of technical interviews.
And I should also make clear that I am not saying become a competitive programmer or a Leetcode expert. For example, there isn't much value in looking at dynamic programming style problems unless you are interviewing at a top company. But spending 30min to an hour a day on easy to medium level questions will definitely sharpen your reasoning about algorithms and data structures. And like I said, in my experience those are used very often in day to day work (at least on the backend side of things). Also, to clarify, I am not saying you should do this forever.
As an anecdotal example, I recently reviewed a PR that had a lot of complex if-else statements that was dramatically simplified through the use of a set. The updated code was easier to read as well as understand. When I pointed this out, the engineer agreed and understood what was going on. But their initial instinct was to use the one tool they knew: arrays and chains of if-else statements. This is the kind of skill I am getting at - knowing enough about your language, data structures, and algorithms to know when to use the tools in your toolbox.
I don't think it is unreasonable to expect a software engineer to understand the difference between tree-based and hash-based data structures, when you should use arrays, and pros/cons of linked lists, etc. Practicing this kind of stuff, which is very easy to do in Leetcode, is the fastest way to build this intuition (at least in my experience with distributed systems).
Edit: just wanted to add that understanding these things makes it extremely easy to reason about systems like Redis, memcached, Cassandra, Kafka, etc. If you understanding the basic, then you start having these moments of clairty thinking "oh this is just a big hash table!" etc.
Also, meant to add that thee repetition of Leetcode style questions is super valuable in learning the APIs of your language. Things like "how do I create a hash table? how do I populate it? How do I check if it contains a key?" This is all simple stuff but a lot of new grads aren't as familiar with the APIs. It's not a big deal, sure, but it is also an _incredibly_ easy way to stand out.
In fact, I had a similar "simplification" moment during the summer after practicing Leetcode for a few weeks. There was a longer than needed function that returned a list of unique items, and realizing the intent of the code, I simplified it to a one-liner using built-in data structures. Small moments of recognition like that feel great!
Your point about becoming more familiar with your language's APIs is also a great one. After the aforementioned Leetcode practice, I didn't have to look up things half as much as I did previously about Python. It was a good feeling :)
Unrelated to the above anecdote, I recently started following the Backend Engineering Show with Hussein Nasser [0], and he makes a lot of these kinds of connections to popular technologies like you described.
EDIT: forgot to add the link!
The level of understanding of git you need to stand out is very very limited in my experience. Most devs in "regular" companies struggle to understand even the basic rebase. Even on a logical, abstracted level. Never mind how and why it actually works as well as it does.
The types predicaments I see people get themselves into even with git vs say subversion is mind boggling. I have never gotten myself into a situation that wasn't resolvable by simply making sure that everything I try is done after committing my changes. You can just always go back and retry. And just slapping a label (branch in git speak, sure) on a commit before force pushing after that rebase with lots of conflicts so that I have a backup. And even that is not strictly necessary. I've fucked up conflict resolution only to notice when the build server tells me and I had to go find a commit hash in my terminal output somewhere to resurrect it (I guess I was lucky I didn't hit an auto cleanup of dangling commits in between ;))
I am really surprised by your comments about git at "regular" companies. If all we are talking about in this chain is understanding workflow and how to rebase, cherry pick, etc. then I completely misunderstood the discussion.
I have certainly gotten myself into some hairy situations. Since I avoid making massive commits, if things get too bad I have always been able to quickly resolve the issue by just doing a clean clone somewhere else and moving my changes over. As a last ditch effort it works quite well and does not take too much time (or stress :) ).
Btw. in case it helps you. No fresh clone in a different place needed. I think I know what kind of situation you mean and all you need is to cherry pick your commit on top of the branch you want instead of doing that merge/rebase that isn't working out. Takes even less time than cloning somewhere else and moving your changes over.
And in some cases what this sort of situation really just needed was an interactive rebase that just skips the appropriate commits that already happened on the main branch. Suddenly a litany of seemingly unresolvavle conflicts doesn't even exist in the first place. Many ways leading to Rome there.
I would encourage you to always work from just within exactly one repo with git. The whole "having another copy of the repo somewhere else" is something I have seen so much with svn but it just really isn't required with git at all. And even if you have to "do a fresh clone" you really don't have to. Just get rid of all files (rm -rf) except the .git directory (or copy it where you need it) and checkout again. I've used that a few times when I was having build issues and I wanted to make absolutely sure there were no generated files from either my IDE or the local build left anywhere that could screw things up.
Beyond bandwagon effects I suspect these tests originally became so popular because they are an unproblematic way to select for people who are highly intelligent but also do as they are told.
This also points to a potential shortcoming of the "grind leetcode" strategy: it is applicable to the extent you meet the above characteristics and even if you do well enough to commend yourself as a high-spec corporate cog, and get that FAANG job, it does little to differentiate yourself against other high-spec corporate cogs (unless you are one of the tiny top fraction of competitive coders, maybe).
So with the exception of mastering algorithms (as taught in uni beyond leetcode needs) or mastering C++ or Java[+], I wholeheartedly endorse your advice, but becoming really good at some suitable and economically useful X is, I think, a more widely applicable strategy with a higher ceiling.
Also, I find it interesting that although I explicitly mention that my idea of learning git deeply would involve the ability to implement it (rather than memorizing the man-pages, say, and presumably validated by actually taking a stab at it) a few people pointed out that git is essentially too pedestrian to be useful. This is not the case, in my experience: both in that understanding git well will go way beyond the antiquarian and also in that lacking git skills are in fact a productivity drain at many or most companies.
[+] Algorithm courses at uni seem to gravitate towards what's neither interesting nor useful. Of course, go a head and concentrate of C++ or Java if your interests require it (e.g. Games programming). Otherwise, I suspect the best languages to master early are either python or javascript. If you care about machine learning or science, master python, if you care about web and app development or graphics, master javascript; otherwise pick the one you like better. Either will deliver much better bang for the buck in terms of skilling up and being able to do interesting things in a short amount of time than Java (which risks pulling you towards enterprise antipatterns unless you have good guidance) or C++ (which requires mastering an enormous amount of antiquarian knowledge to get anything done). I would maybe complement this with learning enough C to be comfortable with heap, stack and pointers and enough Rust, Ocaml or Haskell to have a glimpse at what a language with a proper type system looks like.
There is no harm in reading through Pro Git (which is a fine git book) either, but generally, and I wish I had been more acutely aware of this myself when I was at school, if you really want to learn something you have to either implement it yourself or use it in anger in a realistic setting. It is useful to read about stuff to get more of a feel for what's out there, but you won't get a good understanding of anything you will need to actively engage with it, and it a setting that practically matters to you. From personal experience: it's easy to trick oneself into a superficial sense of knowing something and coming up short when called upon to either implement it or use it to solve a real problem. So my number one advice would be don't fall into this trap; do (hard for you) things in a way you can't cheat yourself (and get them working first before you make them pretty).
So give it a try, the winter break should be long enough to get it done, and if you find it's beyond you at the moment, you can always scale back your ambitions and tackle it once you've grown in ability.
This is so true! Only towards the end of my formal education have I begun to learn the same thing. In many ways, I’m still biased towards just reading things —- partly because implementing something and running into issues I feel I’m not knowledgeable enough to solve/failing really bugs me —- but I’m gradually learning that failure is just part of the learning process, and doesn’t imply I’m incapable of doing something.
I’m definitely going to try it out over the break! :)
If you want to spend a whole winter break + semester (which is a very valuable amount of time), is there anything else you're interested in that would also line up with your career interests? That might be a win-win for the academic exercise and practical benefit
The main issue for me is that my interests are a bit too broad. Should I learn web dev from my job by day, then try to implement an OS in my free time by night? I know I can't learn everything, but yet it feels like there's so much I really _do_ need to know to be a competent developer.
You value practicality as well as personal interest/fulfillment. Either pick one and start there or pick both and consider the options there. If you want to be practical, learn the most marketable skill that you're at least somewhat interested in: Java, AWS, Docker, Javascript are all incredibly marketable. If you want to go for interest, just pick the thing you're most interested in. You could also try and juggle two deep dives, at the cost of more time and less depth, but maybe that works for you.
Don't worry about becoming a senior dev in a semester. Pick something and focus on it. That could be an AWS certification, building something in Java, etc. Once you get through that, then decide your next step.
There really isn't anyone on the planet who is truly a "full stack developer" and competent from the front-end all the way down to the OS and bare metal. No one.
Most developers stick to a particular layer, and are only familiar with adjacent layers to the extent of being able to have arguments with those developers. A 5x-ish developer is competent in those adjacent layers as well. A 10x developer either has mastery of their chosen layer, adds additional competency layers, adds competencies on the connecting tech between chosen layers (ie. not just front-end + backend, but networking too), has relevant domain competencies, or some combination.
So, just pick an entry point, learn as much of it as you want, check out whatever is adjacent, follow your interests, and periodically evaluate whether you need/want to change course or dig deeper into technologies, tools, domains, etc. wherever you happen to be. Even if you end up wandering quite far from where you started, the experience and knowledge you gain on the way isn't likely to be "wasted", unless it is mastery of some in-house tech or tool that literally no other organization uses.
Separately, "the stack" is inherently polyglot, and even aggressively pruning the selection wherever possible and eliding many formats, tools, and protocols still gives you an absolutely minimal set like JavaScript, HTML, CSS, HTTPS, TCP/IP, SQL, C/C++, Assembly, & VHDL.
Maybe a better choice is something like CSS: there's actually a lot to know about it and a lot of companies need people who are good at it for their core product (even though it's not as deep a topic as say being very knowledgeable/skilled in functional programming).
Granted in any sane company this should just be done by the devs themselves. But as the OP said, in most teams knowledge about versioning, branching and version control is very very limited. Even if all you know is how to do a rebase of a longer lived feature branch easily in git (skipping the commits from the other branch) you will be the wizard that everyone goes to. Many many devs will not even attempt a regular rebase. It's black magic for them.
If all you desire is a cozy job in a large company with braindead processes and policies this sort of thing is probably enough to be tipping the scales towards: well we shouldn't lay off that guy coz he's the only one that can work the version control magic AND he codes like mad.
If you wanna stick out in a company filled with John Carmacks you will have to do better, sure.
Her and one of her colleagues are the de facto git gurus in her entire department of over 100 people. She's ended up owning tooling in their build pipelines that is quite complex, using libgit, etc... That tooling was eventually exported around to the rest of the engineering teams (~1,000 total engineers). Now she gets random, challenging git (and perforce, to a lesser degree, and she stepped in to help with some SVN issues at one point in time, though those projects have moved over to perforce, I believe) questions from the entire engineering organization.
I do agree with you, though, that git is probably the wrong thing to focus on and that she and her colleague are outliers. But, it's interesting to see nonetheless.
It's clearly just an example, but whether it's a bad one or not is debatable. Git is used by most shops, and most people have challenges with it at one time or another. Further, it is IMO an excellent example of how choosing the right data structure for a problem can have a profound impact on the resulting application. You could do worse for broadening your knowledge of ComSci than by a deep study of Git.
On the flip side, you are now a source control/build system engineer, and it's pretty easy to get typecast as such (given the outsize impact your specialist skillset will have).
I just started some client/contract work with Spring as API/middle, I'm curious about your opinion on Spring especially on this context of Careers. A niche to be avoided?
"I'm usually advocating for undestanding deeply the problem and being an expert in the matter, not in the tools that solve it that come and go quickly. But in reality it's ok to be learn the tool, as it also brings you knowledge on the same matter, eventually. It may not be as comprehensive, but it's still desired. And people who understand tools that solve the problem are also needed and it may fill some real world needs."
I find it very relatable, as I'm kinda doing that at my work. I'm no expert in anything but solve problems very skillfull coders embarrass themselves at. Not that they are dumb. They are smarter than me, more expierienced as well. But they often lack a wider view of the issue, don't take account so many things. The OS in their code, neglect the existance of network, delays, assume weird things about how other software work and so on. The almost always neglect that people just lie sometimes or will fight to death to prove they tested corectly while I know they made trivial mistakes while testing. All people do. I just verify that once more. Sometimes coders ask me (after I help them with an issue) what apps do I code at our company, while I don't code at all. It would take me a year to Hello World using company internal standards. I just troubleshoot a lot. I know options. I read what you guys write here and try to understand what problems you have or don't have when using different aproaches. So I can suggest new ways of debugging, solving issues, simplifying things.
I like my job. Except for the part when developers lie to me, but in general it's a cool job ;)
For any fan of Carmack, Doom (the game), or just video games in general, I recommend reading "Masters of Doom". Carmack's story honestly reads like a programming/general nerd rockstar in the book, and it's a lot of fun. Also helps me understand what kind of personality it takes to be considered one of the best ever at something: for much of his early life, Carmack was essentially awake just to program. His home was basically a mattress and a computer at one point, IIRC.
Dungeons and Dreamers was a side by side story and contrast between Carmack and Id's path vs Richard Garriot and Origin Systems.
The History of the Future features a much older John Carmack at the top of the industry, joining Palmer Lucky and a team of young entrepreneurs to build Oculus and VR. The entrepreneurial and technical ride is at least as wild as the one in Masters of Doom.
Carmack is saying learning something deeply, for example learning all features of a tool, helps in the long run, but in this approach it takes a while to provide value.
An alternate approach is to learn a subset that provides immediate values. In the case learning only the subset of features of the tool that are being used at that time. That's more tractable and allows you to provided immediate value.
He is leaning towards the 2nd approach because first groups of people are opinionated without broad experience.
Elon Musk said something very similar. He said, lets say you need to use a wrench, but if you start from the very basic it would be extraordinarily difficult to start working. Instead you can just starting learn about the wrench and go backward from there. This was you are providing immediate values to the work at hand.
I think he is overall suggesting that you should find your business value - your value as an employee to the business you work for. He seems to be specifically talking about "career advice", as advice for employment, so slightly outside of his own experience.
He is suggesting a shortcut to this business value is to know one tool deeply enough that you become the go-to person for that tool in your company (whether or not that is in your job description).
I read this as John suggesting a stair step path to "learn deeply". If you can section off one defined area, a tool, it's possible to learn _that_ inside and out in a reasonable amount of time. Then you're useful and people want you around. From there you can expand outward or down or whatever.
This would be as an alternative to dabbling, learning the most commonly known things across a wide area.