I've left jobs over a few reasons, primarily bad managers, increased compensation, and bad code .
If people are writing bad code at your company, to the point where you know it's going to come back to haunt you later, it's okay to just walk away .
Don't embarrass anybody, don't escalate to a manager and explain how horrible the code is. I was in a situation where someone our team was effectively writing code that pretended to do things it really didn't. I got into a really nasty argument with half my team about this. I ended up putting in my two weeks, and then my manager was like oh you were right the entire time .
Life is too short to deal with incompetent people.
When you wrote ‘don’t take things personally at work’, I was expecting you to say things things about various kinds of humility – trying to make requested changes in code review instead of pushing back, not feeling wronged if someone rewrites something you wrote, etc – and seeing the bigger picture – the code exists to serve business purposes and sometimes priorities there don’t align with your more narrowly focused desires for the direction the code should be changed in.
I would say that the rest of you comment gives examples of taking things quite personally – feeling such strong ownership over the code that you’ll quit when you can’t control it as well as you’d like. To be clear, I’m arguing that the beginning does not match the rest of the comment, but not really about the overall message, which to me feels to be more something like ‘you are not required to be loyal’ than ‘don’t take it personally’.
It wasn't a matter of, oh I would have done this differently, it was more like this company is full of people who have no idea what they're doing and I'd rather not be here .
I will say you should absolutely never talk about code issues at a current employer when interviewing. Who's ever interviewing you is going to interpret this as you being some weirdo who argues over tabs and spaces. There's not enough nuance communicated.
Maybe I'm trying to say you shouldn't take it personally when a company isn't a good fit.
Tactfully navigating this kind of thing in code review takes practice.
In my experience, the best teams of programmers work through problems with their egos held to the side.
Much fewer devs can just jump ship at will than between 2003 - 2022.
Usually when people are putting broken code into the code base it's a wider cultural problem, that you're not realistically going to solve.
Citation needed. Good developers are just as in demand now as they have ever been.
If all the people who care about a problem leave, it becomes harder for the organisation to solve the problem. This is one form of organisational rot.
Most of us are good at one and bad at the other. Eg, my instinctive response has been to quit my job when I’m not enjoying it. And that’s fine, but some of the situations were almost certainly salvageable. And I could have helped. Some people try to fix a workplace indefinitely, even to their own detriment, and even when the situation is probably impossible to fix and they should just get out of there.
I think it’s really important to learn both skills. And remind myself when I’m stressed that they’re both options.
The important thing to realize is that bad developers who are kept around tend to survive because they're well liked by people who make the decisions. If you raise concerns about their performance then you're picking a fight that you can very quickly lose. I've seen people get hung out to dry when they escalate concerns about people like that, and even if they were right it still leaves them in a much worse position for their next job hunt.
In most cases I'd tend to agree with OP that the right move for an employee in that situation is to lay low and start looking. If the situation isn't yet completely unbearable there's no need to just hand in your two weeks' notice, but it's worth looking for the exits.
Hear me out.
You're going to then publicly embarrass another co worker. Not a good idea.
I need to clarify though, there's a difference between functional code that could have been written better, and code which does nothing at all .
I was at a company where three or four people literally were writing code that did nothing but was appearing to function correctly. Imagine an API that checks the status of another service, and you just code it to always return 200.
Instead of trying to save an organization from itself, you can just go somewhere else. I did so and I got like a $30,000 raise.
I find it therapeutic to externalize to inanimate objects.
Why did I leave? Because I grew a little bored of it and wanted to try something different. I wanted to try and build my own company. Which is going good so far. (It's been about 14 months since)
I am not my job and thus it gives me freedom to pursue things because I want too.
IMO, one of the biggest reasons for this, is coders that know that they won't be around to have to clean up their messes.
Sort of a "chicken and egg" scenario.
This is one of the main things I try to impart to junior folks when I’m mentoring them or reviewing code.
It’s also one of the biggest red flags to me of someone who’s working above their level when I have to repeatedly press a more senior person to dig deeper and fix things at a deeper level.
You need to take the time to understand why the bug happened, or you’re just going to be patching wallpaper instead of fixing the plumbing leak.
I think many would like to probe deeper but aren't afforded the time between sprint tasks. Management often pushes back for solutions that are good enough compared to exploration with an unknown duration until the solution is found.
(And of course, sometimes just patching the wallpaper is the right course of action, but it's rare to find management capable of accurately assessing this trade-off.)
> If you can't easily explain why something is difficult, then it's incidental complexity, which is probably worth addressing
That's a real eye-opener. Hope I remember this next time I implement something complex. The thing is, I don't think this stuff would've helped me much when I was a junior dev. A lot of them are just too nuanced.
There's also a chance it's not understood yet to easily explain it.
A key part of joining a team is remaining open to the fact that just because I don't understand something, doesn't mean there isn't understanding in it.
No one can explain why the Collatz Conjecture is so hard to prove. It must be because everyone is so stupid and is adding incidental complexity to the problem. Why is everyone so stupid?
Or, maybe, possibly, that advice is utter bullshit nonsense and some problems are just hard for reasons that we don't fully understand. Go write a reliable reactive library that works how people expect. Oh, you can't? Better explain exactly why it's so hard then, or it's obviously all your fault.
That advice is so utterly at odds with actual reality that it makes it clear this author should be completely ignored.
Oftentimes, research papers and similar are written for an audience that is already deeply ingrained in their representative topic, such that those first principles aren't discussed anymore, so perhaps that's where you're coming from when you speak about how "no one can explain ..."; but I would argue that many people can, and have. It may just take a lot of speaking, paper, drawings and similar.
And even if / when there are obscenely difficult things to prove, the chances that the thing the proverbial "you" is working on is one of the incredibly difficult things is very unlikely.
There's a saying that a sign of actually understanding something is being able to describe it to a child. It's also why Thing Explainer and ELI5 exists.
Collatz: if you replace 1 and 3 with arbitrary parameters, Conway showed that this class of problems is undecidable, so any particular instance could be arbitrarily hard.
(Blasphemies warning)
- Skip low level and go as high as you can. Ditch C, assembly, hardware. Take python, ruby, js. Never touched C++ cause it’s awful? Good.
- All the money is in the hands of a client. If you’re taking it from someone else, best case you’re taking less than a quarter for essentially the same job. Useless leeches everywhere who perceive you as a magic money generator. Go around them once you’re confident.
- Read sicp, htdp, taoup, but don’t take them to heart. Seriously, extensively test any idea you learn against reality, cause ideas may sound excellent out of context.
- Pragmatic is the only way. Don’t listen to industry peasants jumping through imaginary hoops, they are crazy. Religion in programming is worse than religion irl. There’s insane amount of it in programming. Don’t argue, let them be. It’s actually easy to test approaches by yourself and learn your own ways. Most of these are just habits making no difference once learned.
- Doing something together only turns out faster if you’re very good communicators. Good communicators are rare and you are not the one.
In my personal experience, I think that having to work on different high AND more low level programming languages over time is what sets me apart from people/coworkers with low basic knowledge of computer foundations (the order in my case being Basic, Pascal, C, Perl, C/C++, PHP, JS, etc). Also it depends on the projects, but just my two cents.
Knowing the low level will prevent you from shooting yourself in the foot with the high level.
So, I guess:
- Learn how sockets, filesystems and processes work, read apue, learn how jits/compilers work. But don’t write serious C, that’s a waste of time even if you’re smart enough.
My better advice would be to avoid work that involves outside clients unless you own your own shop or freelance for yourself. They're always going to be price and deadline sensitive in a way that makes for shittier work conditions and lower pay. Working on well-funded internal projects that generate revenue is the way to go. Your work conditions are also going to be much nicer because a client being an asshole can't be used as an excuse for constant overtime or other BS.
The one exception is “Bad code gives you feedback, perfect code doesn’t. Err on the side of writing bad code.” My experience with bad code is that it does not tell me much; instead, it presents inscrutable and baffling mysteries. From the caveats and examples, I think the author is trying to say something rather different; something like “don’t obsess over completeness” or other concepts of ideal software - especially, I might add, dogmatic concepts of this nature.
My advice to me: write simple, dumb, repetitive code, but make an effort to be consistent.
Consistent, dumb code is really easy to visually parse. The repetitions slide into the background and the differences stick out. The more code there is, the easier to see what goes together (data aggregates/structures), what the overall flow should be (control, conditionals, order etc.). Then it's easier to factor things out or how to express more clearly what the code does.
But again, consistency is key. The code can be "bad", but it's very beneficial to do simple edits like renaming and reordering of things, grouping them under succinct comments so the structure stays clear.
Younger me would do the opposite: inconsistent code that is complex. I think its impatience that gets in the way, rushing to build abstractions and factoring out things way too early or trying out competing ways to express the same kinds of things (playing around with code).
Every programmer has their own tendencies and their own journey, so they need to hear different advice, in order to ignore it for now, but to have an AHA moment at some point when they realize why the advice was given.
i.e. in most cases the cost of bugs is so low that the benefits of a faster feedback loop greatly outweigh the benefits of a more rigorous development process.
(On top of that, the number of defects asymptotically approaches zero with greater effort invested, i.e. diminishing returns.)
When I began coding I spent hours tweaking my vimrc file and learning all the essentially random shortcuts, and dealing with the absurdities of vimscript. (and debugging vim plugins that broke each other.) It felt like actual work while I was producing nothing.
Now I just open vscode with default settings and I am productive right away. Who cares about editors, vscode is good enough.
But maybe just vim sucks and I should have been playing with emacs all along, I don't know.
Typing speed is nice but not an important metric I don't think. It's like someone speeding past you on the road only for you to see them at the next red light. Other things will slow you down like code review or needing to wait until a set time to deploy. Also things like copilot and advanced auto-completion are making it less relevant.
I am right away distracted by a huge rectangle around cursor line, current word highlighting and general jumpiness of everything. Coding in vscode feels like writing a book in the middle of brazilian festival. And then it cannot do random simple things like proper indents or humane snippets. The amount of work required to unfuck vscode is really comparable to creating .vimrc from scratch.
That happened with me, and I'm now a big fan of functional programming, Clojure, Scheme etc., and that experience and exposure to a particular way of writing code has undoubtedly made me a better programmer. It sounds like you've had a similar experience with Vimscript :)
So you might think, until you meet a fervent Emacs advocate that doesn't know anything about "the underlying Lisp stuff".
If I have to hunt down a bug or have something with a lot of touch points, yeah, there's probably less typing and more thinking.
But if it's a new mostly self contained feature usually I think for a bit, then get to the point where I know what I need to build and the next step is about shitting out a mountain of code. Being able to go from nothing -> mountain in a fast time is useful.
i never thought typing speed is all that important when you code. But he DID write crazy fast.
Producing something doesn't always need to be the goal. Exploration has value.
Who cares about other editors, vi is good enough.
I take it that you've learned vim (otherwise you wouldn't be "productive right away" - you wouldn't even know how to input text or save a file) whereas you had apparently never tried vscode before. How can that be a fair comparison?
The time getting up to speed on something new shouldn't be used against something else that is already familiar.
Now if the new tool (ie., vscode) could import your neovim setup and get you an equivalent, that would be neat.
Comparing the sunk cost time for neovim vs vscode might be a more interesting comparison. Neovim definitely is a little more polished than vim out of the box so it's entirely plausible it's pretty close.
If a vim user wanted to learn something like vscode, they could just install a vim extension in vscode to navigate most of vscode in vim keys. Lots on youtube.
It's hard to use a web browser without a vim extension installed.
It's true if you have sunk the time to super customize a setup for you in anything (currently I'm working through my Aerospace setup), the part that I get caught by sometimes is that something I had to customize in neovim, might already be built into vscode, or something else, or vice versa.
Repetitions is about creating the muscle memory, similar to building the same keys with vim.
I'm lucky I was able to get to a place of comfort with vim when I had lots of free time.
It's great when I don't have my setup with me, but my setup with neovim was a step forward, but vscode still sometimes just ends up where I am, and I figure out how to get it behaving a little better.
It stuns me how many devs do this stuff manually, when virtually all editors/ides have ways of doing these things.
In my experience, lisp also has this issue of being very difficult to tool in a general sense, as did aspects of writing c/c++ years ago (maybe recognizing stuff like macro-generated symbols has improved by now).
I view time spent learning to use my tools efficiently and automating common tasks as a sound investment. Editors are a great example. Sure, I could fire up any of the usual suspects and write code somewhat productively. But in my fully customised editor of choice, I can insert and adapt common code patterns that would take me 10–30 seconds to type out fully in mere moments using templates and macros. I can jump to any position visible on-screen with around three keystrokes. I can see syntax highlighting for various file types that I use all the time, including some unusual ones that don’t have definitions readily available, and warnings for several different programming languages in real time as I work.
These save me a few seconds every time I use them, but how many times is that every day? The effort to set them up has probably repaid itself 100x over by now! And the lack of latency is also a qualitative improvement since it means once I’m ready to start writing, I can do so roughly as fast as I can think, instead of constantly being held back and interrupted for a moment.
For code-editing, maybe. But in general software engineering, there are tasks that I have to do maybe once a year or less that are always way more painful than they need to be because I don't remember the details, and anytime I automate even part of them (or yes, just document a little better), it turns out to be well worth it. Stuff like bootstrapping new environments, some database-related work, etc.
I use it so much that many non-technical people at my company have started adopting it as well.
Is always so painful to watch how slow average developers are with the tool they use the most. Using mouse/touchpad to scroll/select word is unbelievably slow. Learning and configuring text editor that is customizable enough to not get in a way pays dividends really well.
Programming is mostly reading and navigating through the code with "go to definition" and similar code actions. Just being able to do this really fast would give a huge productivity boost right away.
Maybe I hit the point of diminishing returns. Maybe it’s because I don’t Code Like Hell much anymore, but it’s a habit I got out of. I keep resolving to getting back to it, but the fact I don’t maybe telling me something. Like maybe I’ve filled that spare time with other things that are more valuable.
Honestly, yes, I think this is it. Ok, vim doesn't suck as a text editor, but it sucks if what you really wanted was VS Code. Emacs, however, doesn't suck. I spend very little time tweaking my Emacs config these days, but when I do it's to fix things VS Code users just have to put up with. I've watched over their shoulders. They put up with a lot.
Then there is also the collective argument that letting Microsoft have editor monopoly can be really disastrous.
i am much junior but from my experience, working with the toolchain of your team is better in the long run than against it.
if you become proficient quickly with whatever your team works with, it is much better overall than making everyone accommodate you. i have worked in teams where getting neovim installed would confuse the IT as they don't get those requests (or may not even know it exists!).
In the corporate world be very good at administration. You only need to just be good enough at programming to not get fired. Everybody has opinions on software techniques and nobody measures anything, so it’s really just a popularity/tool game. The only goals are retain employment or promote out of software, being good at software is just a distraction from the goals.
If you want to be excellent at programming do it as a hobby and set your expectations right that it’s only a hobby.
Also be vary of someone saying that just because things aren’t measured it is just an opinion. Most important decisions you make won’t be measurable (a lot will though), that does not mean there aren’t good and bad decisions.
There's that old (and very true) wisdom that if you solve a complex problem in two days, the business people won't think "wow, this guy is so smart and hard-working for solving that in 2 days." They will think "oh, this problem must not have been very hard to solve. Let's assign him extra work." Being a good engineer only gets you so far, career-wise.
If I wouldn't keep them separate, I would lose passion to it fairly quickly.
You can only understand them because you lived those situations, which implies experience you don't have.
I would say (specifically to my young self):
- There is no substitute for doing. Less tutorials, more coding.
- Stop being obsessed with quality: you are not at the level where you can provide it yet. Do dirty. Do badly. But ship. Some people will be mad at you, and they are right. But do it anyway. Yes, reboot the servers with users on it. Yes, commit the spaghetti. You'll reach the level you want to avoid doing all this.
- The users don't care about the tech. They care about the result.
- Doing something for the hell of it is worth it. Just make it separate from the point above so they don't conflict.
- Programming is a battle against complexity. Again and again. Put that on a post-it. Make your decisions based on it. You will suck at it, but try.
- You have imposter syndrome because you are an imposter. You are really bad. It's ok, doctors hurt people for years while learning to save them. Don't sweat it. It will come.
- You need faith it will work out. On the long run, you'll get better at this. But in the short term also. You'll find the bug. You'll figure out the solution. It will happen if you keep at it even if it can be frustratingly long and unfair. Even if it doesn't feel like that right now.
- The right team is way more important than the right tech. If you are alone, get in touch with people who will lift you up from time to time.
I have come to the conclusion that the use of these sorts of posts is not that the reader, young or otherwise, will instantly and correctly apply all the lessons to their lives.
It's more about sensitizing people to problems they may not currently see, and solutions they may not currently be aware of. It's about shortening the learning curve, rather than eliminating it.
A 1-year programmer is not going to read themselves into a 20-year programmer, no matter what they read. But at the 5 year level I think you'll see a lot of difference between someone who never considers their craft and never pushes themselves, just keeps their heads down and doing the next bug, and the person who has even just occasionally read this sort of post, pondered how it may apply to their current situation, and taken out of it what they can... which may be something completely different than what they take out if they read the exact same post two years later.
Also this was just an analogy I know, but doctors definitely don’t hurt people for years while trying to save them, very different profession from ours, if anything doctors earlier in their career have been shown to have better results.
E.g. this tip:
- There is no substitute for doing. Less tutorials, more coding.
is directly addressing a common mistake for absolute beginners. Many beginners will read (or worse yet, watch) loads of coding tutorials while doing little themsves. It is an issue a complete beginner encounters and understands.
Your tip on the other hand:
> If you (or your team) are shooting yourselves in the foot constantly, fix the gun
is addressing people working on medium to large projects with internal tooling. That is not a situation a complete beginner finds themselves in; it's a situation someone who already works in programming for a while finds themselves in.
I wouldn't necessarily say your tips are too abstract; they are simply too high level for a complete beginner.
That is not necessarily a bad thing; perhaps the you of 15 years ago already had the basic understanding necessary to be able to comprehend and make use of your tips.
My experience with doctors, of which there has unfortunately been plenty, is that the older doctors are much better. If I need something delicate done I want a doctor who's 50-65ish. They know what they're doing, they don't screw around, and they've seen enough to know that yes, your case is the common thing they've seen 500 times before, and that this treatment works and that one doesn't.
Typing skills are severely underrated in order to professions and roles adject to our professions like PM.
> - There is no substitute for doing. Less tutorials, more coding.
I'd rephrase that as "just write something!"
Many times I find myself being the classic example of 'perfect is the enemy of good' - I'll think about the perfect solution, rather than write something *now*, that works, and refactor towards perfect. TDD and all that.
Other things:
- Beware the beta and the boss. If it works, it will invariably get shipped if your manager sees it. Many managers cannot put a value on the future cost of maintaining something that's barely good enough.
- Classic Confucius: "I hear and I forget. I see and I remember. I do and I understand." If you're interested enough to read about some tech/language/framework, write something (again!).
- Learn at least one other language and ecosystem in addition to your main one. Even if it is syntactically similar (C++, Java, C#, for example).
This may be good advice for yourself in the past, and for many people at lots of times, but I'd hesitate to give it as general advice. Reading code others have written should not be understated as way to learn valuable things from fundamental patterns and algorithms to language features and idioms. If you have a job in a team, this may happen anyway, but it's possible to write lots of code without realizing there's a better way.
What in the medical malpractice?
It is ok to be an imposter.
- don’t read opinions from a list and take it as gospel. Adapt to the jobs you’re in, and you’ll develop your own opinions, but now with experience to explain why. Opinions are formed by getting repeatedly hit with the consequences of your (and other’s) decisions, and everyone just has to take enough hits till the pattern seeking area of your brain takes over.
There are roles I've been in where it's only been years later that the true impact of decisions made was actually apparent. I'm glad I hung around long enough to experience that.
For example, if you can’t decide between two data structures or tech, pick one and add a comment:
// I’m not sure
> - There is no substitute for doing. Less tutorials, more coding.
Motivation, productivity go out the window. You don't give a sh*t about the work, team, code quality, made up deadlines or real issues.
Real maturity comes now. You learn to appreciate your limits, see what really matters despite what's being said and observe who make the calls and what their agenda is.
And finally, when you've picked a path and it seems like it works, you'll find equilibrium, somewhere between an idealistic comment on a PR and your next interview.
Till something else like health or kids rock the boat.
Take it easy, you matter more to you than your work. 15 years on, only ones who will remember the weekends you spent at work are your family and kids. Get out more, find solace in the varied arts. Enjoy you painless body till it lasts. Make the weekdays show up between weekends not the other way. Laugh more. Eat well. Feel your surroundings. Make friends, keep friends. Make memories. Don't throw your life away chasing menial pursuits. If a piece of work is really that substantial and meaningful, it will show itself as such. Don't go looking for it.
You'll reach the level you want to avoid doing all this.
What if future you has reached that level and people on your team are shipping spaghetti?
Consider this just a rant from an older programmer who hasn't fully recognized that 'programming' is now largely a social endeavor with online info for everything, language and library ecosystems, etc. I wonder how much of this information I would have internalized if it were all available in my time. Seems like the kind of thing I might read and nod in agreement and forget to apply when relevant without some hard earned run-ins (which is how I'd picked them up).
As for actual programming advice, the thing I'd highlight is to look at the data first and foremost. It goes from initial conditions to post conditions. The differences are what your program/function does, but both the pre/post conditions should be able to be fully described as a valid static state. Once you understand that, the problem, the code is largely plumbing with a small part that applies the functional transformation. There's so much focus on the form and style of "the code" that seems to consider it the main thing rather than an artifact of getting the main thing done: think any time there seems to be fancy abstractions that don't provide value to offset its complexity. To relate it to a point in the post, if you can't connect the difficulty you're having with the logical transformation that needs to be done (e.g. from database state to state), it's likely self-inflicted (or it could be due to a poor choice of database schema). Similarly for poor choices of request/response formats--basically bad plumbing between systems (and not intrinsically hard because of the information being handled).
This is a great use for new, standalone open source modules: feel free to experiment with styles or techniques or goals that you wouldn't want to justify. (Or for experiments that you start and then abandon without ever showing anyone.)
For example, when I was making lots of packages to help build out the Racket ecosystem, I'd already made an HTML-writing package, but I felt a craving to do one that used syntax extension at compile time, rather than dynamic s-expressions. So I just did it, as a separate package: https://www.neilvandyke.org/racket/html-template/
I don't recall anyone saying they saw value in it, but I like it, and I scratched that itch, and added another skill to my programming mental bag of tricks.
Modern medical education doesn't work this way.
It totally does.
They make grave mistakes all the time. And they hide them. They lie about them.
They have their ego and career on the line.
And they don't have enough resources at their disposal, not enough hours, too many patients, and they are exhausted.
In short, they are humans in a human system.
You learn by doing x time. There's also a place for study, reading, etc. to supplement this.
This is true in software development. It's true in martial arts. It's true in chess. (the 3 things I've invested some effort in progressing in). I've taught martial arts but there's no magic advice I can give people that will instantly take them to the next level, they need to experience and work through things to progress. Having a teacher helps (a lot).
But it doesn't matter. They were designed well, they were fun to play, and millions of people enjoyed them.
Is it because we start adding abstractions before we understand the problems?
Like, there's a certain threshold where keep things too simple makes them too complex, so people start introducing abstractions to reduce complexity. But often it's the wrong abstractions and then we accidentally end up with worse complexity that's harder to unravel.
There must be a term for this waves hand thing?
Edit: gosh typical on phones is hard
Seriously, you might be inexperienced or not know everything, but you should clearly not be an imposter and you should be confident in your ability to improve and understand what you don't understand yet.
Take responsabilities and ownership in what you do, don't get behind the easy excuse that it's too complicated. You are the professional and you are getting paid for this.
I think you're likely to reach that level a lot faster by trying and failing than by not trying at all.
Most adults are kids in big meat suits, they fake it a lot.
I started to live like I was not completely worthless at 35.
Not saying that to be proud of it, just stating that if you think humanity should do better, the first person you'll judge is you.
It will be glaringly obvious you are not meeting your own standards.
The higher your standard, the longer it will take for you to reach them.
And the way to get there faster is to ignore the shame, and do it anyway. Because if you don't, your growth will be slower, and you will do more damage for longer.
Real life means real consequences.
It will make you more tolerant of others as well. Way more tolerant.
Seasoned, grownup engineers and tech business leaders are forgetting this, even today. Users don't care that your product is made with AI, but techies just will not shut up about Generative AI, LLMs, Transformers and all this shit that should be implementation details. Users don't care about any of what goes into the sausage.
- learn functional programming. Doing that was how I finally “grokked” programming and could solve problems more easily. Before I was ready to give up.
- learn CS history. I studied UX and what I learnt was mostly one side of how to think about computing where you spoon feed users and remove things. There are other ways to conceptualize software and design, which would have left me less disillusioned.
- learn fundamentals: data structures, networking, performance, operating systems, security, unix, math. These are so neglected in the industry, and we’re left with super complex systems we don’t actually understand as a result.
I sometimes hold a "command line fundamentals" course for my teams. Just being able to understand the basics puts them above any team that doesn't.
You have to know the ground you're building on. Otherwise even your foundation will be faulty.
Exactly, well put. Knowing the fundamentals leads to a more solid, safer foundation as you understand better what you can do with what you have and avoid layers of abstraction.
This one is good and has been following me since I've became a manager. Thanks to you, I know how to apply that objection to "press" people when I feel we're dealing with this kind of complexity.
Fundamentals:
- Ecosystem beats language and syntax
- Use boring, battle tested technologies
- Use the relational database to do the heavy lifting
- Avoid caching unless you have a great reason
- Code cleanliness comes from simplicity, not elegance
- There's higher leverage from improved code reading ability over writing ability
Professional:
- You grow faster building in good industries over interesting codebases
- There's higher leverage from improving the business over improving the code
- There's higher leverage in finding mentorship over being an autodidact
- Make T-shaped buy vs build calls: build the secret sauce, try to buy the rest
Probably leaving a bunch out.
"In situations where bugs aren’t mission critical (ex. 99% of web apps), you’re going to get further with shipping fast and fixing bugs fast, than taking the time to make sure you’re shipping pristine features on your first try."
In 99% of web apps, your end users have no possible way of telling you that you shipped a bug, and your bug will remain there forever, frustrating users and losing your client money as they abandon your site. Telemetry won't help you either becuase you'll misunderstand the observations it provides.
Very important! But also important to distinguish between kinds of quality. Using a sub-optimal algorithm or bad identifiers or copy-pasted code can always be fixed later. But some problems like a bad database schema is much harder to fix later.
I have seen far too many teams using Facebook sized solutions for a few thousand users.
I’ve seen developers slowed to an absolute crawl, terrified of shipping code, for a completely secondary operational platform with low volumes and non-critical data. All because the product people were misguided in their mission.
And sadly, I’ve seen teams with almost non-existent security practices and knowledge happily banging out crap in financial services environments.
And I’ve been blessed with teams understanding their position and fully embracing it. Financial services products with quarterly releases that were rock solid and well architected. Batch document processing systems with just a few dozen end users who worked closely with us developers to tune algorithms where sometimes we would ship multiple times in a day and re run batches in production.
To be successful, teams gotta know if you’re at NASA level, or life threatening, or business critical, or somewhat critical, or just nice tooling, plus understand the cash flow / budget situation. As a dev you may not be privy to all that, but strive to know as much of this as you can.
And of course, understand who you users are, and who your customers are, and prioritize accordingly.
- Always think how to simplify the code you write, since simple code is easier to maintain and debug.
- Prefer writing dumb code than smart code. Smart code is good for programming contests. Smart code is very bad in production when it needs to be debugged or refactored.
- Always think about improving the usability of the software product you work on. Users don't care about code. They care about UX of your product.
- Fix small usability issues as soon as you notice them, since these issues are usually the most annoying for end users.
- Do not start writing code with some popular design patterns. Just write the most simple code, which resolves the given task. Later, the best design patterns will evolve organically from the code solving the particular task.
VictoriaMetrics development goals are based on these rules - https://docs.victoriametrics.com/goals/
I spent a ton of time doing support and engineering on a trading desk, where our SLA for an outage was somewhere in the range of 30 seconds to 5 minutes. Having super simple code that makes it easy to understand what the code problem is (if not necessarily the business problem) lets you move on with life and let the business keep moving.
(Keep it simple stupid!)
And yes, users will notice the button that is only half visible quite a bit more, than a suboptimal sort algorithm.
Learn to become comfortable implementing and working on state machines.
It might be one of the most useful abstractions out there that if implemented well leads to a great extensible design without compromising performance.
Early in my career, I spent a lot of time reading unclear or obsolete documentation, poring over code, etc, when I could have asked the person sitting next to me and gotten an answer in 5 minutes. Sometimes, I didn't even know who the right person to ask was, but if I had just asked my tech lead, he would have been able to point me in the right direction.
Claiming that it reduces your overall time from several hours to < 5 minutes is maybe a bit exaggerated, since it also takes time to figure out what question you want to ask in the first place. But it's still worthwhile even if you end up investigating for 30 minutes instead of 3 hours.
One, reading code in general is a good thing to do when you're new, and it's a skill that should be built up in general.
Two, you might actually find what you're looking for, and answer your own question! It's a nice little boost to realize you're getting self-sufficient.
Three, you'll have a lot more context for me, which will make it easier for me to give you the answer. "Hey, how come this function doesn't return what I expected" is a much harder question to answer than "This function says it returns a list of items a user has accessed in a given workspace, but it's returning an empty list; I've checked my local database and it has a good set of seed data I think, and from looking at the function there's nothing obviously filtering out users, so what's going on?"
A lot of the time, you'll answer your own question getting to Y. If not, it will save the person you're asking a bit of legwork, and show you are not trying to have them do your job for them and have respect for their time.
It's hard to find the right balance, and I agree with the author's framing of it as a spectrum, but I also agree that I at least (and most junior engineers, in my experience) leaned way too far on the side of being, um, self-motivated.
I certainly do notice myself getting frustrated by people asking questions when IMO they should know better, and I'm never sure whether I should be more lenient there or if I should tell them off for not putting in that tiny bit of effort.
I think the problem is knowing when to ask is like many things a skill that gets better with experience. It isn't obvious especially to newer people. I also think if you're a senior you should be much more forgiving of juniors when it comes to this stuff. We were all there once.
I think asking too slowly tends to be caught more easily in things like standup before it snowballs. Asking too quickly tends to be habitual and seems to do more damage since it's harder to notice when managing projects, and often under the vague auspices of "pairing."
Next month I’ll have been working in software for 30 years. Which means I would have a lot more common ground with me 15 years ago than most people will. that me with five years’ experience might not have understood at all.
Me with five years’ experience suspected many things that were true but missed some important one. I’d probably have to feed his ego by confirming some of those things before moving on to the difficult bits.
But who is to say that me with less Impostor Syndrome would be a better person? No, the main value in learning from the past is improving the future, not nostalgia or regrets or what ifs.
There was a while where too many jr devs wanted to learn it all and go through the phases of learning everything themselves without considering if others have maybe gone through something similar.
Thinking one's self not qualified might mean you share a good thoughtful approach towards learning something.
Thinking one's self is qualified and if it's too soon might mean otherwise.
No matter the better I have gotten, having a healthy mistrust of one's work helps it become better in a lot of cases haha.
This is probably quite a cynical way of putting it (and it speaks to me, probably because I am quite cynical) though I don't know if a junior dev will really appreciate this.
The way I would put it is: don't seek satisfaction from trying to make perfect abstractions for business rules no one quite understands, rather seek satisfaction from making your user's lives easier as efficiently as possible.
A reasonable argument might be that it should be watched / policed but this is harder in practice than in might seem. A lot of orgs are fairly decentralized, meaning that no central entity can make the call (probably a good thing imo). If appropriate constraints are designed into the system this kind of energy sapping discussion will not even need to happen in the first place.
Essentially, adding constraints at t0 adds degrees of freedom in the future. Coding is a bit like a garden - you need to ensure that the garden makes sense as it grows.
I hear this advice constantly. But I feel like it really need to be qualified. I have been in projects that never saw any real value produced because people constantly focused on DX, projects management, and other tools.
Sometimes one just needs to do with tools at hand, and not worry if there are better tools.
The situation appears to be changing rapidly. 15 years ago there were no advanced code-generating LLMs, and while relying on them for the core logic without having a good understanding of the language and system is still a bit iffy, it does seem that they're pretty good for generating tests and spotting deviations from whatever your group has decided are best practices.
I worked on a system that used the protobuf types generated for communicating between services everywhere. There was absolutely nothing in any of the components of the system that didn't depend directly on the generated protobuf code. What made it even worse is that a backend system we called had multiple endpoints that used the same name for similar but slightly different things, so there wasn't, e.g. just a single Passenger type, but a bunch of different Passenger types across various packages.
I often do this, but have been doing it less frequently, lately, because I don't want to force a thread switch, unless I know that I'll be calling UIKit functions (not always things that affect UI. Many "background" UIKit functions also require main thread). Instead, I clearly mention the thread state, in the API headerdoc description ("- parameter handler: A simple, no-parameter, tail completion. May be called in any thread.").
Ideally the task you pivot to should require minimal context switching to get going. This way you won't lose productivity. Often if the blocker is a hard problem and you go back to it later, you might have a good idea after stepping away for a bit as a bonus.
Too many engineers think their job is “great code writer” and not “value adder”
- Engineers spend way more time reading code than writing it. So writing easy to read code is more important than writing fancy/complicated code just because it saves few lines of code.
- Extension to above point. Having coding standards in the company is important so that it's for anyone to make changes to different parts of the code. If one engineer ends up writing code using their own standards, it makes life harder for everyone else on the team every time anyone else has to debug that code.
And remembering to ask questions hits home pretty well too. There's always the worry that you're bothering people too much, and the balancing act between thinking whether you need to be asking for help early enough to make sure you're not going down the wrong path and not asking about every little thing without attempting to fix it yourself...
my advice would be much simpler: 1. Most of the time you'll be manipulating test. Learn options how to manipulate text professionally. That includes vim, bash, sed, awk, perl, and regexes in general, including lookbehinds etc. It's worth it. It takes a few years to learn but even the basic options give you the culture and approach how to do things faster. Most coders have trouble swapping two columns in a text file or finding unprintable character.
2. Learn hotkeys seriously. They're more consistent and uniform than UI, learn how change them, which tools are better designed for them, and organize some memorization scheme. It pays off a lot and gets into body memory, freeing up mental space.
3. Learn how to version your own code instead of creating multiple files and folders. Read git manual at least once. Learn how patches work, what is interactive rebase, and how to go back and forth, combining different changes from different branches. That gives you freedom to experiment with code on a larger scale.
4. Learn how to quickly test any framework/code. There will be countless situations where you have some piece of crap not producing the needed result, and you should be able to quickly prove it. For this p.1 is invaluable. I have my own json,xml,rest,kafka and text log parser and diff, and a few cloud, database and search clients which I tweak when switching jobs. It's all mostly written in standard unix tools, and can be literally retyped if needed (I worked on high security envs often). It's also isolates me from poor (non-)standard tooling different in every enterprise to which I only fallback when I already know the answer and need to prove it to a peer.
The rest is subjective and optional. You can love or hate your job, you can love tabs or spaces, weak or strong typing, but the above will definitely makes it faster. What to do with the rest of that time is your decision.
That’s how I feel about git.
But I think git became so ubiquitous that even new solutions unburdened by needing to mimic git's data model end up bringing that complexity forward because of familiarity.
This is a reasonable step to take if you're working in a reasonable company with reasonable "management". If you're unlucky enough to be working under a manager that refuses to recognize there is a problem, even with compelling data, prepare for pain. In that case nothing is allowed to be done because "well, that's how we've always done it and doing something about it might upset someone". It's really time to quit and find something new at that point because there is generally no hope of turning that around.
> If you can’t easily explain why something is difficult, then it’s incidental complexity, which is probably worth addressing
See above. "That's how we've always done it, and someone is used to that work flow, so we can't change it." Sometimes this will lead to a legitimate Chesterton's Fence situation, in which case you'd want to regroup and rethink it. Otherwise, the batshit insane is the default. Target the latter.
> Try to solve bugs one layer deeper
"There is no time to do that! We have so many other projects!" While being blind to the fact (or better yet, burying their head in the sand and trying to ignore) that it's all self-induced.
> Don’t underestimate the value of digging into history to investigate some bugs
"We can't change that because one of our people close to management made that decision and it might drive them away." Good, get them out, that's the only way to really fix it. Ideally if the management that hired them is pushed out too.
> When working on a team, you should usually ask the question
"Who are you to question our wisdom? Who are you to suggest something else, it's working in production."
These are great things to start conversations, but you have to start them in an organization that is willing to change and be willing to take your advice to heart. Don't waste your precious life trying to change what can't be change, no matter how much you want to see it change.
You should be able to give anyone in your team the repo URL and have them running unit and local integration tests in five minutes without prior knowledge.
What does people use that is faster to process both for devs and the PM?
Use the tool as a tool. As the devs, add issue and tasks that needs the attention of the team, comments on a ticket for knowledge retention. As the manager, schedule the ticket if its completion matters in a particular timeframe, use assignments and other fields to manage workload. Do all of these to help the team get things done. Anything else is a hindrance.
Why does the author mention JIRA as a process? Does he find it slow or convoluted compared to other tools? Or does he think that using JIRA means a PM is forcing the team to follow an unwanted process?
To avoid the mess, design with the fail-fast principle in mind, which brings you closer to the spot where an error occurred.
Finish what you're doing.
I'm one of about 2 people at my company who goes on archaeological expeditions to understand when and why a bug was introduced. A nonzero number of times, I have found that the behavior was introduced on purpose over a decade ago, and sometimes it's addressing an edge case I didn't think about. History is valuable!
(unfortunately the most common usage for me though is as a 'smell test' where I learn who wrote the code from the history and then decide based on my existing assessment of their skills, how suspicious I should be of that code)
e; oh yeah one more story that's kinda funny. Just this week I saw some behavior that I didn't like and went to look at the code's history. I was the one who wrote the code I didn't like. But I had left a good enough comment on it that I realized there actually was no issue at all and my expectations were incorrect.
When the subject of "tech debt" comes up, I always tell the teams I work on to focus on tasks that improve our speed or agility in the future. I believe that many coding tasks actually have a negative dev cost over time, as they reduce the dev costs of future work more than they cost at the current moment to implement. (Of course the problem is that they have a positive dev cost in the current sprint, so good luck convincing decision makers...)
Programmers love to think this matters. If you're doing anything more than the most rudimentary work, the time 'saved' by maximizing keyboard shortcuts is completely irrelevant. You're spending most of your time reading code, thinking about that code and thinking of what code you're going to write.
When any programmer emphasizes how fast they are at completing these rudimentary tasks, my assumption is they are less adapt at the actual work of programming and instead try to 'git gud' at the keyboard wizard bullshit.
Whatever lets you sleep at night.