Things I’ve learned in 20 years of programming
daedtech.com
daedtech.com
1. learn how to communicate: being a good developer requires as much (more?) social as it does technical skills. I would recommend formal training and practice.
2. question all assumptions.
3. there is no silver bullet (read mythical man month).
4. fight complexity and over-engineering : get to your next MVP release.
5. always have a releasable build (stop talking and start coding).
6. code has little value in of itself; only rarely is a block of code reusable in other contexts.
7. requirements are a type of code, they should be written very precicely.
8. estimation is extrapolation (fortune telling) with unknown variables of an unknown function.
9. release as frequently as possible, to actual users, so you can discover the actual requirements.
10. coding is not a social activity.Being a "Developer" (planning, designing) is very social, however writing the actual code, for me at least, is a very inward activity and suits my quiet personality. The problem here is that non-coders don't understand this and it can cause a lot of friction when working in the usual group office environment.
It's a catch 22, people want me to code for them, but then they have a problem with me socially when I'm trying to code ;)
Thanks for the quick reply.
I worked at companies that had full time pairing and it worked well.
When you tried full time pairing, what were the issues you observed that made you conclude it was "moronic"
1. At some point in the 90s there was an "Extreme Programming" movement, or XP as it were. I distinctly remember the dogma built up around this, to the point where I started being forced to do pair programming in a formal sense, all day. Thankfully I just quit. I guess I prefer my coding to be less than extreme.
2. As others have mentioned, short term pair programming (never works >2 imo) is an excellent way of transferring knowledge (a model) to someone else, or to make progress on complex problems when you are stuck (the rubber duck effect is real).
3. I'm afraid I really must be getting old as I've never heard of "mob programming", and to be frank I've spent the last hours being horrified that such an idea exists. I guess in a way code reviews can be like that sometimes. lol.
One place I was at did everything, including onsite customer etc. In context pair programming managed to stay enjoyable for the entire time and they didn't seem to have high turnover. It actually kept on feeling more productive. I was there around a year (contract). I never encountered it again so can't comment if that was sheer luck or the people (or project) they happened to have...
There was a spell when every job ad seemed to want to claim it, but basically picked pair programming and two to five of the bullets and handwaved or ignored the rest. Or merged it with plenty of old school waterfall project management, Gantt charts, random bits of UML or some other tangent. I guess I'm not surprised so many ended up hating everything around XP and pair programming as it took many forms. It made for a few surreal interviews after that one encounter of an employer who'd adopted it fully and properly.
In fact, I dare say that pair debugging is where the practice really shines. Doing it all the time, for all tasks? That won't fly.
But I guess this is but the original intent of pair programming
I've never lost track of time coding like you say - I stop at 12:30pm for lunch and then at 5:00pm to go home. I've always wondered if I am doing something wrong or maybe I just like programming enough as a job.
I've found that I experience a kind of embarrassed reluctance to fully commit all my attention to something while I'm at work surrounded by people, that prevents it for me.
Perhaps related, perhaps not, I never 'sink in' to films I'm watching. My old GF seemed to be able to, but I'm always on the outside looking in, never immersed. I wonder if that's linked.
Parasite the korean film?
Nothing magical about flow, but feels very productive even though one might be working on the wrong solution all along! For gaming industry and huge codebases, programmers absolutely need to get into flow in order to manage to complete it all in time.
For me flow is very pleasant but I don't get to experience it often, maybe once a month. It always feels very productive. I can be in a light flow state where I am still slightly aware of my surroundings, but on rare occasions I have experienced deep flow where I am aware of nothing but my internal monologue and the code. I daydream about being able to get into that mode sometimes.
My advice is to find some way to take some pride in the work you do and or change employers when that flow stops happening. life is too short not to.
But then there are many successful ones who follow a schedule and still create amazing body of work. For example - Roald Dahl. Based on the notes in his books, he was someone who followed a daily time schedule and he did alright.
So, do what works for you I guess.
If it's boring or boilerplate it doesn't work. Otherwise, some kind of flow normally happens. I believe you require some amount of concentration hence the need to not be interrupted, and it has to be a bit challenging to require concentration.
An example would be an interview or college exam: you are pressured and needed to stay focused, yet the time passed very quickly.
Some of us do most work in stretches of "flow" that involves disconnecting our minds form the outside world and from the people around us. We "go deep" like in a state of trance for stretches of time. We probably work faster, but we also need more and longer breaks between these stretches of hyperintense work. Others like you (maybe most?) can work while aware of time and their surroundings. It's good that we're different, each approach has advantages and disadvantages, we all discover what works best for us individually... just respect the needs of the people around you, let them work however fits them best!
As a "flow-er", the most important skill I've learned is how to be productive even when I can't get into flow. As a non-flow-er, you should probably learn the opposite: find tasks and ways of working that can help you discover "flow"... even if you won't experience it very often, it's worth experiencing it!
1. learn how to communicate: being a good developer requires as much (more?) social as it does technical skills. I would recommend formal training and practice.
2. question all assumptions.
3. there is no silver bullet (read mythical man month).
4. fight complexity and over-engineering : get to your next MVP release.
5. always have a releasable build (stop talking and start coding).
6. code has little value in of itself; only rarely is a block of code reusable in other contexts.
7. requirements are a type of code, they should be written very precicely.
8. estimation is extrapolation (fortune telling) with unknown variables of an unknown function.
9. release as frequently as possible, to actual users, so you can discover the actual requirements.
10. coding is not a social activity.
1. try to engage at work with more activities, you'd be surprised what activities you can help out with, or maybe arrange.
2. never pass up a customer focused activity, volunteer and push to be involved.
3. ask a sales or business guy at your company to be a mentor.
4. talk to random people beyond small talk (parties?).
5. read books (mileage varies).
Something like "toastmasters" for coders would be so cool.
Mostly, though, I can tell a grizzled veteran (and I've known some that hardly had any years under their belt, it's all in the soul!) because they rarely claim to know The Answer, and have a weary self-confidence that, even though they don't know how, they will get the job done.
Last year, after experiencing several individuals that fit the term, I came to calling some people "Medium Developers" - generally falling in the 4-8 years of experience, that get much of their knowledge from Medium articles, and believe the dogma wholeheartedly. Complete lack of nuance in all things, and are very evangelical about their dogma. Shitty managers are enthralled with them, and the code written (slowly) in such situations is horrific. "Throw it out and do it the Right Way (tm)" is the mantra.
Honestly, the blog post in the OP sounds like a Medium Programmer. They're worship of TDD is one symptom!
"I don't know, but we'll figure it out" is what I like to hear, versus, "This is how it Must Be Done!"
I think getting to this point really helps with the "flow" issue ("coding is not a social activity"). The more you can isolate small steps, you can more easily weather interruptions.
> They're worship of TDD is one symptom!
My suspicion is that this person is very good at writing the tests, at the right level of isolation and detail, and that watching them work would feel less dogmatic that the text of the blog post suggests.
I've had this argument multiple times recently. Usually when I say the former the response is something like "But how can we really estimate it or plan it before we know exactly what we're doing"
Writing overly detailed requirements without coding gives me the same feeling of fidgetiness you mention. My attitude is "Plans are worthless, but planning is essential" , and you have to cut off design at some point because the risk (that you discover something in coding that invalidates the plan) outpaces the value (of knowing what you're doing).
Reminds me of another problem I've seen recently - an obsession with writing code that is "overly correct". There are times where a small change of a few lines accomplishes a thing but produces some undesirable side effect - it breaks an expectation somewhere, for instance. But the alternative is rewriting a huge portion and adding a ton of code and adding complexity as a result, even if the methods and their responsibilities are more clear.
"Throw it out and do it the Right Way", in other words. We've become very conditioned (especially mid-career) with focusing on never allowing tech debt and doing it the right way. But sometimes you actually add complexity in trying to achieve perfect cleanliness. And in fact, even if the resulting code is slightly less complex, there is a lot of risk in the rewrite.
At my stage of my career - 15 years - the biggest conflict I see is between business that wants estimates and the inherent unpredictability of writing software. Business wants the list of things I'm going to get done, meanwhile I want priorities. Are you able to say "Hey, this thing I thought might take a week is actually a quarter long project, should we set it aside knowing that?" Often the org is simply not flexible enough to handle that (or handle scoping it down so it can get done in a reasonable amount of time).
I'd almost say what you describe is the sign of a mid-experienced manager, too. They've realized it's important to shield their team from some organization problems so they can write quality code (moving past the "yell at them until it gets done" phase). But they haven't really learned how to get past the mid-level engineer obsession with beautiful code, or to handle the general complexity of the inherent clash between business goals and engineering goals - they've gone full towards the engineer side of that spectrum.
I wish multiple tech leads I've interviewed with, here in Berlin, realised that. There's just so much cargo-culting around XP.
Seems to take people a long time to figure out (4) and (6).
(2) and (3) and (7) really apply to most things.
20 years of programming has taught me to avoid working with people who take themselves so seriously and think they’ve figured it all out. 20 years has taught me the importance of compromise, give-and-take, and following as much as leading. It’s also taught me that there are people who’ve only been doing this for half as long that are 10 times better.
Although I have less professional experience than you, around 6 years combined in software development and information security, I've also come to appreciate people who find the right balance of taking what they do seriously without being uptight about it.
Which brings me to a trait that almost always puts a dent on my respect for anyone regardless of seniority: not asking enough questions and being quick to make statements.
I loathe this so much that I've turned the opposite into my work mantra: "no statements until there've been enough questions".
IMHO, this "small" tweak changes one's interactions and their outcomes with other co-workers for the better.
Shame I can only upvote this once. Avoid like the plague. B Players, natural vs institutional authority etc.
Oh you've been ~programming for ~3 years and you're now a thought leader - fantastic delusion.
Just because you have the entire system in your head right now, will you when you revisit it a year later to add a feature or fix a big? How much time will it take to internalize completely? Tests allow you to know less about the system overall and still make assured changes to smaller portions of it because prior you (or someone else) has spent the extra time to make sure any mistakes are caught early and easily.
The go-to counter to this is that you should really know what you're doing and understand the system you're working in, but that's often not only infeasible, but impossible for one person (how well do you know all the libraries you're using?). There are plenty of codebase out there where I think no one person can internalize it all and understand it well enough to always make food choices, and since you'll have to choose what you want to remember, a helpful tool to make sure you don't violate some important facets of how it works is useful.
Now, much of this is about testing in general, but if you think about it, there's a lot similar about writing new code and coming into a large chunk of code that you need to alter but you have limited understanding of or poor recollection of. The same things that keep you from violating how it should function help your design a coherent functionality in the first place.
When one is writing complex logic that is supposed to receive both frequent new features and keep working correctly there is nothing that beats TDD.
Let me attempt to compare this to bowling even though I know nothing about bowling. If you just occasionally like to go out bowling you can use whatever technique you like and you will get better if you just bowl a bit more often. If you want to play bowling on the national level you may at some point have to drop the technique that you made up yourself when you started out. You need to go through the uncomfortable stage of learning a new an better technique and temporarily be worse at it. I think the people not doing TDD are just refusing to go through this because there is not much of an objective standard of quality for developers. We are in a field where code that lacks any sort of quality is standard and where breaking features three times a week is standard. TDD will fix these things.
The reality is most projects start as exploration. What you’re thinking might not even be possible. Can you even approximate the classes you’ll need yet? For these scenarios TDD fits in awkwardly.
I prefer to do a little back and forth. A little dev. When things are looking stable, a little resting. Towards the end a lot of testing.
There can indeed be exploration stages where TDD does not help that much. E.g, if you are going to interface with a piece of hardware you have never seen before and you need to get some sort of working communication going there is much point to what you say. As soon as you know what sequence of commands makes the piece of hardware work one has arrived in the territory where TDD is highly beneficial. You can then write a test where you require that your software indeed produces the correct sequence of commands and after that you can refactor your exploratory code while having to check that it still works together with the hardware much less often then otherwise would be needed.
The remark about TDD and waterfall seems much less true to me. In my original post I wrote 'both frequent new features and keep working correctly'. That does not describe waterfall at all. In fact, and this is where you messages seems to get a bit self-contradictory, your post actually sounds much more waterfally to me than mine. It contains the words 'Towards the end'. It is waterfall projects that have an end that was envisioned right from the start. Whatever 'agile' means, it seems to have the feature that we never stop adding features and that stuff is supposed to be in a working state in between adding these features. So, if one is actually doing that there are dragons in the sentence 'Towards the end a lot of testing' because it actually turns into 'always lots of testing' which costs lots of time. In case of the hardware example it would also require that every developer has a species of that hardware on his desk next to his computer. As I happen to work in a field where we interface with hardware that is three stories high, we should realize that this is not always practical.
One misunderstanding that might be going on is that perhaps you are assuming that in TDD one would test just one class at a time. I generally prefer to test a set of classes, i.e., a subsystem of a whole program. In that case the test are about properties of the program that, in many cases, the user could recognize as beneficial. There should be less churn at that level. I suppose some people would call this behaviour driven development instead but I am not so very married to terminology and will just keep calling it TDD. Testing individual classes can also be helpful but if they contain rather simple logic I am not sure writing tests for that is so very helpful. At some point would just be testing whether the processor really is capable of copying values which is not that interesting.
LeetCode / CS101 problems are almost always like that. In the real world, it's also useful to separate out any tricky "policy" logic into nicely testable pure functions. But you are still going to have a bunch of side-effect munging left over, and unit testing is terrible at that. Tests that only assess their own mocks are a waste of time.
And what do you mean by 'Tests that only asses their own mocks are a waste of time.' Certainly, many side effects can very effecitively be checked by mocks. Now, it could certainly get much more difficult if the side effects were very large and hard to define as you said in the paragraph before that, but I have some difficulty picturing that as a common situation.
It's not really about being close to the hardware[0] - there's many other things that are unrelated to low-level performance tweaks that make TDD or even unit tests a waste of time for experienced game developers.
When someone like Blow or Carmack sees an automated playtest fail, they have a honed intuition for what caused it. This intuition was built up over many years of hard-earned experience. They simply don't need the lower level unit test that says "this matrix multiplication math is wrong" - they'll see a collision fail or a weird scaling thing and _know_ right off the bat the candidates in the codebase where things went wonky and fix it before you can even say "look at the logs" :) Since they get the same results without having to write unit tests everywhere, and especially without writing tests first, it's simply an unnecessary overhead to make them write/maintain it.
I don't think anyone would argue TDD and/or unit tests are valueless, it's just a cost/benefit question. Pretty sure they'd use any technique where the benefit outweighs the cost- and for them, for many reasons in many varied scenarios, it just doesn't.
[0] actually, if anything, I'd bet that the stuff that's really close to the hardware like the core engine stuff (math, memory management, etc.) is the one place they would consider having TDD and/or more unit tests!
If you can’t write code well in the first place, you’ll write terrible tests, and then even more terrible code to make them somehow succeed.
I’d argue TDD has value in the first case, but most teams are more like the second variant.
In my experience, coding is the easy part, and pinning the relevant stakeholders down on what they want coded is the hard part. If you're an employee, the hardest part of your job will be in a.) understanding what'll make your boss happy and b.) communicating how to make that realistic. If you're a B2B business, the hardest part of your job is figuring out a.) who your customers are and b.) what they want. If you're a B2C startup, the hardest part of your job is identifying a market with lots of people who want your product.
If you're a maintenance programmer where these things were hammered out a decade ago, then TDD can be a godsend. If you're working with an excellent business analyst / salesperson / cofounder who can hammer these issues out with enough precision that you can trust their answers, TDD is helpful. Neither of these situations describes the gaming industry, nor a number of other very lucrative industries.
I don't see your point. You'd still have the same problem if you had a team gold-plating some other code instead of doing their job. In fact, without TDD your problem is far worse because you don't have checks in place to evaluate if some code works as expected.
While in general the advice on duplication is reasonable I think it tends to get taken too far and the example is a poor one.
Presumably for now Mexico applies a different sales tax % but there are so many unknowns on how Mexican tax rates differ that I'd keep the method separate until I'm certain the abstractions are similar, otherwise you might end up with:
calculateBill(locale, appliesExemption, exemptionRate, regionalTaxRate, nationalTaxRate, clothing Untaxed)
Premature abstractions seem worse to me than some duplication.Besides something like bill calculation should have loads of tests.
But there are good and bad principles. Like avoid copy paste. But I would never say, never copy paste code. I do, when I hack something together quickly and if it stays it needs later refactoring. No problem there .. only if the refactoring part gets forgotten bugs sneak in.
Also the advice of less is (usually) more.
Witing code is easy. Writing good code which is working, readable and maintainable is hard. But as little as code also goes against readability.
So like many others here said .. dogmas are stupid. There are different szenarios and just use what works for you.
Usually I start with reproducing the bug in specs, with at least one or more specs failing due to the bug. Then I go on to fix the bug and see the specs turn green. I think TDD is pretty well suited for the use case.
They are functionally the same tool beyond one config file setting defaults and another config file managing access to components of the tool. After playing with the differences, we iced the broken app and updated the setup KB with the config differences.
As we upgrade the core app that the vendor tools work within, we are glad this headache had a quick fix but is being cut as the new version of the application natively supports what the tool did in the old version.
That being said, don't use this as a reason for doing that or at least document that for the future owners of the tool so we don't waste what little time we have troubleshooting functionally identical software.
It depends on a lot of things; such as what kind of complexity the project's modules are prone to (algorithmic complexity or integration complexity), team size, security requirements and reliability requirements.
It's very important to keep the testing as minimal as possible at the beginning. Sometimes minimal means a lot, but you need to be able to justify it because tests (especially unit tests) lock down interfaces and functionality and this can go against agile principles. If your project is innovative and requires that agility.
After 15 years experience coding on many different projects and companies, what I learned is that blanket statements are often unhelpful. You need to critically evaluate every case as unique and make arguments about why and how your case differs from the norm (and it usually does).
Flushing out the architecture early is the trickiest part for me. Occasionally I miss a seemingly-simple feature that ends up requiring an architecture change. If this happens late in the process, I may pay for the oversight with hours of refactoring.
The way I heard it from an English professor:
Writers write. The only way to become a better writer is to write more.
I wonder if there is a correlation between amount of knowledge and Impostor syndrome kinda like the four stages of competence. At the beginning, you may think you know a lot but as you get further along, there's less and less confidence that comes with more knowledge.
I am advocating for knowing the costs and benefits of your refactoring decisions. If you can't predict what the costs are, take that as an indicator that maybe you should avoid refactoring, just yet. Consider as a litmus test discussing costs and benefits with people whom it will affect and try to reach an agreement. If you dread the thought of having that discussion, you probably ought to avoid refactoring. If you can't argue in favor of your refactoring idea, it's not worth the effort.
Also, consider that just because you can re-use flexible designs doesn't mean you will. You may not be the best person to consider the probability of re-use. Assume that it's unlikely: YAGNI (you ain't gonna need it).
Zen of Python. The exceptional beauty of John Carmack. Rebases of Google Style. Dive into a Linux Kernel. Very Objective Apple Style. Infinite pains of TensorFlow. Simple magic of SQL. Clarity of PyTorch. Unique ways of Prolog. Formality of Antlr. Frictionless Microsoft Style. Completeness of Theano. Abstract Syntax Notation One. Eldritch style of Michael Abrash.
Maybe analogous to mixed strategy equilibria from game theory.
- Code duplication should be avoided, but not if the alternative is complicated or highly-coupled code. Duplicated code is increased liability, and complicated code is increased liability. Sometimes two similar but separate functions is just easier to read, use, test, and maintain; assessing the "liability" helps you make the best decision.
- Tests are good because they decrease liability of other code, but they are themselves are a liability, so you can go too far (as many other commenters note about TDD).
And "Code is a liability" is not a silver-bullet. It isn't specific or prescriptive enough, and that's a good thing. It requires experience and effort to understand what that means and to make use of it on a case by case basis. But I think it does point you in the right direction by posing the right questions and focusing on the important trade-offs.
100% agree.
Along these lines, avoid applying DRY principles to "incidental duplication"; You can end up coupling completely unrelated code if you are blinded by removing all duplication.
Programming is a ridiculous career path.
I am in my early 30s and I am aggressively saving as much as I can while living very frugally, to hopefully retire multi-millionaire abroad or get a lower paid job that won't stress the life out of me before I turn 40. Hopefully I won't become unemployed before hitting my target, or die of a stress-related heart attack.
I am not completely disappointed about my career choice because it allowed me to save a lot of money (see note), but boy, it is an insanely ridiculous career. Very frequently I wish I pursued something else, there is just way too much and fresh new crap keeps coming, every week. Can you believe 4 years ago almost nobody was talking about containers/Kubernetes? Just to name a random niche. Can you imagine what will happen in a couple years? They say "it's all the same, it's a cycle, you already learned it": that might be true if you are a manager or a PM and you just need a very superficial overview of the ecosystem, but if you are a senior engineer you need to master your craft, so even if a technology has been reinvented you need to spend hundreds of hours learning the details of this new incarnation, that's literally what your employer expects. Ask an engineer if being proficient with VMWare is enough to get up to speed with Kubernetes just because one is the sequel in the virtualization scene... exactly.
Also add the effect of globalization: my company hires talent from Eastern Europe (not consultants, entire teams with local management, product, ...) who produce insanely high quality software products at a ridiculous pace, exquisitely documented. Those people are wicked smart and on top of that work 20 hours a day. I am surprised software engineers are still hired in the US, where working 10 hours a day is already considered unhealthy. I feel the same way as a brick and mortar store that's going to get pushed out of business because of the more efficient and cheaper Amazon.
Note: It also helps that I choose to live in the super expensive Bay Area while not wanting kids, so I don't have the same spending requirements of people with kids and can bank the spread that most people would have to spend on schooling, nannies, good housing, ... I rent a studio for $2k in a ghetto-ish area, and that's 70% of my expenses. If I had a couple kids for whom I needed to provide good housing, nannies and private schools, I would be spending all I earn and there wouldn't even be an end in sight to this madness.
What makes you think they work 20 hours a day?
If I were to start a company in the future, rest assured I would do 100% of the engineering hiring over there, after having seen their work ethics and productivity levels.
As an added bonus, they are really not in the mentality of profit sharing/equity compensation typically seen in the US, so you can get them with a cheap salary (think ~$50k/y), whereas a local senior engineer would cost you ~$250k + equity, and would demand a good work-life balance and probably resent you because your free lunch is not as good as FAANG's.
ugh !!! yeah, you better be scared for your own job and good luck hiring those devs in the future...its more likely they'd be hiring you.
But yeah, $50k is enough for many to throw work-life balance out the window and at times pull all-nighters - I should know, because just recently I quit a job where that unfortunately was a habit of mine - all for approximately this pay.
I don't think it's sustainable, but younger people increasingly choose this way of life, because it lets them obtain status symbols like a MacBook Pro or a lease for a Mercedes C-Class. Also the overall mindset is that this is how people live and work in Silicon Valley - regardless of whether that's really the case.
But here's the kicker: some in my area are saying that we're in a bubble and developer salaries surely must come crashing down eventually. Others think that our only advantage is low cost.
Personally I share neither of these views. It's all relative and as long as real estate prices in Silicon Valley remain absurd, developers will be compensated generously. Perhaps even after they come down - if they ever do of course.
It should be pointed out whether you mean net (take home) pay or total cost for employer. The latter is usually about twice the former at these salary levels (at least in some parts of Eastern Europe).
For that I get rudimentary health insurance - only really good enough for a hospital stay free of charge.
The tax rate is a flat 19%, so I would wager that the tax wedge is likely smaller in eastern Europe than in the US.
Of course, for that they will only get minimal pension and standard medical insurance. They have an option of voluntarily contributing additional money to the state pension fund to get increased pension.
To make that work though, I'm done with the interview circus. It's been such a distraction over the past 3-4 years, that if I wasn't prepping for interviews or staying up to date with the waste of knowledge that they test for in tech interviews, I could've built a successful business already. Now I'm choosing to focus my time there.
I still have the luxury to do so. So I should take my chances because industry sure isn't taking one on me.
I've found the same issues as yourself. Things have become more complicated and yet I feel like my position is seen by a more "informed" upper-management as a kind of commodity.
I once had a manager tell me, during a pay-rise request that developers where a dime a dozen. Fair enough, that's probably true.
I've been thinking so much the last few years of how to transition into a field with less technological noise. I feel like most other people I work with, their only real skill is in communication - as in they don't have any strong hard skills like engineering.
I'm in the same boat as you. Unable to get married or buy a house, or have a family due to living expenses. I mean the average price for a 1 bedroom in London is uppwards of 350k, I've been saving for 13 years and barely have a fraction of that - I dont know who is buying these houses...who can afford them? or are people willing to gamble with their savings and their future?
Also, I feel like some technical managers dont do a great a job of protecting our field. As they are the ones primarily responsible for communicating with upper management. Often times, they are downplaying our abilities and our position - they dont realise that their accomplishment in terms of generating efficiency is often compromising our job security. Ultimately most managers dont care how hard it is to be a front end engineer or full stack dev or whatever, they just look at numbers, and in many cases they see us a financial burden or as a commodity. So, you as a technical manager need to bare that mind during your crusade to automate and optimise x,y and z.
Your responsibility as a seasoned programmer is not to code !
I'm a 20+ yr experience programmer and still hold the title Sr. Software Programmer and no. I say no.
Yes the stack is deep but it is unnecessarily so. Yes, there's layers and layers ...but it is your job to educate the less experienced why less is more and why there's is always a tradeoff to be made.
Computer science hasn't moved a whole lot[1] in terms of problem solving since the 80s. Computers have just become faster. The best ideas we have today are still rooted in the principles of the 80s. They are just a abstraction level higher.
So no. I refuse to accept the premise that Nothing is easy anymore.
[1] when considering fundamental theories.
I don't agree with that completely.
I do agree with the fact that the half-life of programming knowledge is far too short.
We flip through languages, technologies, etc. before anybody actually gets truly proficient with them.
Stuff that has an incredibly long half life like SQL/Database internals, or OS fundamentals, networking fundamentals, CS fundamentals will serve you well basically your whole career. So even a little bit of time dedicated to these over the long run is time pretty well invested.
A larger portion of learning goes on to the treadmill of technological churn, but that's either stuff you are learning now in order to get your next job working with it or are learning now as a result of getting a job that gave you the opportunity to work with it.
The middle ground is getting deeply familiar with libraries/frameworks that have a medium term half life. Usually that's some form of data access.
I feel very very lucky to have chosen programming as my career.
I've been working in this industry in a serious way for about 15 or 20 years? So not exactly close to retirement but I'm not straight out of school, either.
> The stack is to deep. Nothing is easy anymore. The technology count is staggering.
To me, it's insane how much easier literally everything is, and how wildly more productive people can be.
I remember when I was young, first of all, it was impossible to just get access to technologies so you could learn them. Compilers cost money. Databases cost money. Operating systems cost money. It was hard to even get to the point where you could mess with stuff, for financial reasons. Now, to a first approximation, there isn't really a tier of basic software you'd want to develop on/with that you can't get essentially for free. It's not like they're running some totally different "production-grade" operating system or database at the big tech companies, or that the well-funded machine learning labs have access to some sort of special super computer with totally different characteristics than what you have access to. They basically have the same shit. That's bananas!
Then, there's the utterly massive revolution in programmer productivity that has been caused by the internet + automatic memory management. In the olden days, there was very little code reuse, for several reasons, but one of the reasons was that it was too hard to pull in random libraries and start thinking about who would own the storage for the error string they wanted to return to you out of every single api.
Everyone bitches about how javascript programmers think nothing of adding "left-pad" to a package.json along with twenty thousand other dependencies, but the fact that you can do it is nuts! And it makes everything SO MUCH FASTER AND EASIER.
The other day I was just curious if I could point my webcam and my whiteboard and have it pull in the lines I drew on the board with a marker and save them as some sort of curve in the computer. I have no experience in computer vision or anything like that. I don't even really know Python. I was able to get this roughly working in like half an hour with Python + OpenCV + some driver that already made my camera work + some tutorial that came up in DDG. It's like being a freakin REAL LIFE WIZARD.
Take building Android or iPhone apps. I remember trying to write apps for the Palm Pilot a thousand years ago. Just getting the toolchain to work at all could eat up a couple days. This is reminding me what it was like to try to write a win32 app w/ OWL or MFC, starting from the auto-generated code. Anyway, now, you get a tiny computer with shockingly powerful cpu+gpu+a zillion radios+gps+multiple cameras+gyros+compass+accelerometers+gigs of storage + gigs of memory + a super high rez touch screen. You can assume that to a first approximation, everyone in the high-GDP/capita countries has one of these, essentially everyone in the mid-tier, and the low-tier is growing at a shocking speed. Further, they are all exposed to your code through a more or less universal set of interfaces so you don't really need to worry about drivers and hardware support hardly at all. You want to run some code on here? Ok, you can distribute it for free over the air, and you can write your code in an automatically memory-managed language with a freaking gigantic standard library. Oh also the SDK is free. And there's an emulator that runs on x86. Oh and there's a visual multithread debugger that you can attach to the process...from your computer..remotely. Oh you don't need a dev sdk, all the normal units everyone has, those just work.
But you want to build a network application? Something that needs to talk to some sort of service? Well the good news is you can get a database, an operating system, and incredibly powerful web servers and application servers, and they all cost nothing. In fact, they're already installed, on the computers that you can rent by the minute, and the lowest tier if you just want to mess around? It's free.
Mainly what I feel like is extremely JEALOUS that I wasn't born later. Imagine all the cool fucking shit you could have built as a kid instead of wasting your life trying to find a cracked version of Borland Turbo C that worked right. Choosing between the horrendous performance / security / etc of perl cgi-bin vs. the unattainable per core licensing fees of a "application container" or whatever those special jvm things were called. Oh, here's one: DATABASE FREAKIN DRIVERS FOR JAVA. jdbc drivers used to cost money! And they sucked shit!!!! ahahahahhahaha.
I agree that programming is a ridiculous career path because I can't believe ordinary-talent-level programmers in Silicon Valley get paid into the low seven figures a year to essentially work on their hobbies. This has to end at some point. I can't believe this is a real job. It's like your whole life, you love legos, and you're always trying to build bigger things out of legos, but you always run out of the pieces you need. And the someone comes along and says, "Ok kid, here's the new rules. Legos? Legos are free. Every single type of lego, in more or less unlimited quantities, you can just have those." What's the catch? "The catch is you get paid to play with the legos." Wow thats crazy but it must be like...a barely survivable wage. "No in fact total rubes who just graduated from school are gonna get paid 3x the median income for a family of four in their first year out of school. People who've been around for 10 or 20 years will make like a million bucks or so." But only in like weird big risky situations, right? "No that will be the deal if you work for the most stable boring companies where you get six weeks of vacation and all your meals taken care of etc."
??? How is this possible?!!?!
Amen. I started programming in Turbo Pascal and Z80 assembler in the 80s, and never laid eyes on a manual, book or documentation about them, except for a few articles on assembler I read from magazines in libraries. I had one beginner Pascal book. Now I can instantly download any paper or book, then instantly download anything they reference. Most software is free too.. I love it, but it's hard not to imagine how very different my childhood would've been. I came across a copy of Zaks' fabled Programming the Z80 in a bookshop a few years ago, which I'd never seen before in person, and I was like My god, I would've given a leg for this 30 years ago.
I'm sorry about your copy of Turbo C. Mine worked fine. Still enjoy pudb.
The only "golden age" I can think of was the internet bubble when investors were crazy and threw money on anything that had anything to do with internet. Some kids made really good money "programming" HTML.
And somehow my experience using computers & software hasn't gotten dramatically better in the past two decades. Most of the improvement can be attributed to long term hard work (software that I used 20 years ago is today easier to configure and/or has been replaced by something that is easier to configure, and it's not because they rewrote it by throwing some glue and libraries at python over a weekend) or improvements in hardware.
All the simplicity brought by the magic of new abstractions will go away at the moment you are forced to understand the actual thing behind the magic, realize that most placed that used that magic were probably simpler to write without the abstraction (ex all the both ways data binding in angular would have been cleaner and efficient to do it with events though it would take you 5 more lines of code)
You have blinders on. Programming is a far better, far less risky career, and pays far better than many very popular career paths (architecture, teaching, sports, arts, research (be it science, computer science, or humanities).
Context:
- sports and arts are obvious
- I did my stint in research, and programming (even at FAANGs) is far less stressful and far easier to find a good job in
- my wife worked in architecture / works as a teacher
Or teacher at private schools also make more.
But what a great career for constant learners! I'm glad it's the way it is.
That's what I can't stand about the cult of "you get to learn so much at FAANG or a startup" -- at some point in life, you need to spend less time learning new things and start applying the things you have learned. I've been drinking from the proverbial water hose for 20 years. It's tiring now. At some point you need to be able to find the permanent things and reject the noise.
Well... that's the point, really. If it didn't change then you'd be able to master it all.
The constant change is the motivation for constant learning and (hopefully) improvement.
There's no point in me trying to make a longer point of it. There's an sort of an eye-opening account from someone coding for years about how our situation as programmers has improved over time.
If you're doing it for any reason other than to gain transcendetal enlightenment you're in the wrong space
I'd like to do that job, but last time I checked, there are none.
There are plenty of things where the changes are slow, and 20 year old frameworks are still used up to today.
Or do they just mean doing unit tests as you code?
I'm never sure when I hear this term because the benefits described (thing's just working first try) seem to apply no matter what order do it in.
At a very high level: Write the most basic case and it will fail (no code written). Write code so the test passes.
Now write another test that will fail. Then write code so that tests passes.
It forces you to write code in a way that is testable and you catch any regressions if previous tests fail.
In the end... you shouldn't.... write any code that isn't required to pass a test.
Did you made any effort to adopt and enforce TDD? Because, like any good practice, unless someone drives adoption then things tend to stay the way they are.
In my experience, it has always been easier for multiple developers working on a code base to write the tests once the implementation has been fleshed out and a significant portion of it is 'ready'.
TDD, though, is really a learning system. The main point is writing the code with testability in mind. You can write them together and get the same results as long as you do that. It keeps the code loosely coupled and the APIs clean.
So, IMO, you can still call it TDD as long as you are writing the code and tests together and are writing the code with the tests in mind. You can do that with the pure TDD or with some variant as long as the result is the same. I guess it depends whether you are referring to the general style or the specific learning methodology.
Because, what exactly is the contract? Do I essentially write integration tests to the effect of "If I click input element with css class .username, type 'x', and then click input element with class .password, then type 'y', then click the button with class .login, the page URL has changed from <mysite.com>/login to <mysite.com>/profile?"
There are no clear API interfaces for UIs. A user wouldn't really care that the button had class .username on it, for example -- that just gives us some way to identify the correct DOM element to perform the e2e test against. And some day, a developer could rename that class name, and it'd break the e2e test.
In other words, I can't assumption what TDD looks like for user interfaces, without the whole testing process seeming extremely brittle. Contrast this with, if I call some REST API, I expect this response body. It's quite concrete.
Unless you are trying to test whether clicking on a button or link fires an event, UI tests aren't exactly in the domain of unit tests.
Having seen some of the interesting designs of less-experienced devs, I disagree that this is a benefit of TDD. TDD may help straighten out some of your thoughts if you already have loose coupling in mind, but it won't work if the dev doesn't already have some experience there.
If you deliver a set of scripted requirements (Read documentation) prior to the feature - that’s TDD.
If you change the code, you break the documentation.
After arguing with a friend who claimed to have discovered a bug in `malloc` because his program crashed (that was a long time ago), I figured that there's a hierarchy of probable causes of bugs, from most probable:
1. The code I wrote [you must understand only your code]
2. A 3rd-party library/dependency [you must understand your dependencies]
4. The compiler [you must understand the compiler-generated code]
5. The OS, or OS-provided library [You must be intimately familiar with OS internals]
6. CPU, or other hardware-related [You must be intimately familiar with how the CPU or other HW works]
It's basically arranged according to how many other programs are using the given facilities. Returning to the "buggy malloc", I did not dismiss his theory outright just pointed out that if malloc were bugged in such an elementary fashion, that no other programs could work, hence there was overwhelming probability of his code being bugged, not malloc.
---
Just like security features, error-handling cannot be bolted on afterwards. Robust programs begin with defining error-handling strategies and expected outcomes in case of errors and building the rest on top.
---
I could probably go on, but... meh.
Turned out I was right. And this was his code, not mine. The best part? He had been on the team longer than I had, and this was at Google of all places.
And people wonder why I have lost interest in the field...
By the way, there was sort of a bug in a malloc I remember fixing. Now, when was it. Ah, on 7th October 2006 ;) https://gitlab.flux.utah.edu/gtw/git/blob/dff9d65dc61af8a00a...
From my experience (about 20 years):
1- Obviously...
2- Some libraries are more reliable than others.
3- Missing, are you working for Valve?
4- I sometimes encountered compiler bugs, but it was things like compile-time crashes, never bugs in the generated code.
5- Never happened to me. Or at least no bugs that weren't documented (there is a BUGS section in manpages, read it).
6- Actually more common than the previous two. In fact extremely common in the embedded software business. But even with PCs, bad RAM sticks and things like that happen.
I am asking because for me, writing tests before the code is a natural choice for pure functions where I can easily map inputs to outputs. I cannot imagine writing that kind of code without tests.
But the usual task is gluing together tons of components and 3rd party calls (e.g. starting from an HTTP request, doing some transformations, calling some APIs maybe, persisting stuff in the database).
All of this depends on tons of side effects and hard to mock components. The only test I can write there easily is a full contract that mapping the HTTP request to HTTP response.
This doesn't help me with developing the internals (definitely not TDD), it only verifies the end result.
Even worse if there is no clear response but the result is piped into some queue over the network or something similar.
I am either completely incompetent or I develop applications that are tons of hard to test stuff (especially with simple unit tests) with only tiny core of functionality that seems easy to test.
1. The internal pure data representation. If you're using some state management like redux or xstate then you can just cache the state on changes and run tests as-is (e.g. running the tests would be sending events and then checking that the state is what you expect it to be).
2. The page itself. Tools like Selenium and Cypress will allow you to easily inspect and run tests against the DOM state (e.g. running the tests would be emulating interactions with the page and checking that the properties of elements are what you expect them to be)
3. Checking the virtual dom (or other middleware). For example, with React, you can "get at" its internal data (at least the level you need) via a testing framework like Enzyme.
4. If your app uses webgl context or is simply too hard to test on any of the above "pure data" levels, you need some sort of image recognition to compare pixels. I doubt this is going to be _perfectly_ testable but you can try your hand at Sikuli or roll your own with OpenCV
I think this is a big misconception among devs with less than five years of exp.
Now at 35, I definitely think it's time to move on. I won't lie about my lack of interest in the field. The problems are less difficult to solve, but also much more frustrating. A lot more black boxes that you can't reverse engineer when you get stuck. Working with other people in a big company means things move far slower than my ability to get things done.
Plus the proliferation of different tech stacks means that despite the big job market, most of the new jobs require specific knowledge that I don't have, and my existing experience with low level coding and problem solving don't carry much weight.
None of those jobs _require_ specific knowledge upfront. The problem is clueless fuckwits in HR filtering out CVs based on keywords. General problem solving ability and knowledge of fundamentals means you can actually learn any of the latest shitty frameworks in a few hours on the job.
The part about black boxes you get stuck on strongly resonates with me. Programming can be a lot of fun, when you can rely on your own, or well documented programming.
But enter the world of development in big companies where everything specification never leaves alpha phase, is done in retrospect, only on request, 3 month later then needed and if missing half of the absolutely needed information is the best case, it's just so miserable.
Depends on your stack. Things just kept getting better for me. I was using it before and after the peak and it is still much larger than it initially was.
But hate
No, a woodworker builds furniture, a developer develops applications.
It helps to think of pure programmers as assemblymen working on a factory floor, nothing more nothing less.
I got bored with “programming” about 4 years ago and I belatedly discovered “the cloud” and started moving into more architectural roles I enjoy being able to do the full stack [1] and jump back and forth between the different parts without having to worry about either the infrastructure gatekeepers[2] or having to wait for resources. Any resource I need is just a yaml file or script away.
I also enjoy the force multiplier affect of being able to lead projects.
[1] full stack: front end, middleware, databases, CI/CD, CloudFormation templates, network configuration, etc.
[2] yes at a larger company I would expect to have access to a Dev account to play around with and get my infrastructure as code templates approved.
Web technologies were fun when I started back in the late 90s early 2000s. Learn the basics, build a server from scratch, throw a few languages and frameworks under your belt, and you were good to go. Of course, you can still build things simply, but good luck getting hired without the latest arcane tech stack in your resume (that will no doubt be forgotten in a few years). In addition, web development skills have become a worldwide commodity.
I am done with the web.
One thing I think a lot of us forget is how _lucky_ we are to be working on interesting projects/tech. I started my career as a maintenance coder and if I had continued doing that, I never would have lasted this long...
And yes, though not as often as I used to, I still have times when I have to scratch a particular itch for 24 hours straight or I have to jump out of the shower to test something that just popped in my head :-)
Then one thing led to another and I got a job more on the pure software side of things, and realized as long as there is some interesting problem to solve it's really not so bad what the end application is.
I find a lot of these comments are depressing. I feel like no matter how complicated the stack becomes, computers are made by humans and therefore can be understood by other humans. I always pity people working in medicine who have to debug what seems like a proof-of-concept that has been endlessly patched by evolution for the past few million years into a working product.
But hey, I only have 5-ish years experience working full time as an engineer so I guess I'm still a baby. I wonder how I'll feel about all this 15 years down the road.
On its own I consider this bad advice.
I would change it to 'Always strive to make your code as easy to understand as possible, while less lines of code and complexity is preferred'
— Hokusai
Once everything is separated you feel much more comfortable introducing that specific Mexico change without messing around with the core logic. Of course things that are truly agnostic shouldn't be duplicated but that tends to be extremely narrow in the end and you never know what it is before you have a lot of countries. It quickly becomes a maintenance nightmare trying to fit broad logic to impossible flexibility.
- understand and care about context. Understand the input and output of what you’re developing. Why people need it to function a certain way. And how people are actually going to use it.
- business trumps tech (most of the time). Not just in matter of how well a company will perform financially, but also in everyday developer life. For example : a different business model may imply a different tech stack choice (and that’s just one example). Understand and care about the business side of the place you’re working in. It’ll also helps you greatly communicating with your managers.
Well yeah, more code means more bad code. I'm interested to know whether more code means proportionally more bad code. If not, his statement doesn't mean much.
2. Learn office politics and learn to do it well.
3. Everything else is irrelevant.
How?
I'm favoriting this comment so I can get back to this later.
It's not looking great for the future in terms of staying a developer. It's getting harder to find reasonable jobs anymore. My current one and the last one are/were disappointments.
I think the best words of advice are: Devise a career backup plan. I don't currently have one even though I have exerted effort in that direction. Probably end up a stocker at Home Depot or something. Hope not.
At some point, knowing another language or framework may be interesting to you, but it is pretty much immaterial unless you are going to use it on that job. For instance, I love Kotlin, but there's no Kotlin developer roles in my market hardly. Waste of time. Same thing happened with Clojure. I never learn.
You will be too expensive: I recently went after a Kafka Architect role which I should have been a slam dunk for but when it got to price the other side suddenly got all wobbly, excuses appeared, and poof, it disappeared.
Companies want cheap, throw away talent. I will say it again: Companies want cheap, throw away talent.
I don't even know what the baseline is for satisfying programming jobs. All my jobs have been similar in terms of points of frustration.[0] I've just kind of accepted it as normal.
[0] I would elaborate but don't have time right now. At work.
For myself, it's always been about the team I was a part of. When you are part of a team that takes pride in their work, and they perform well together, supporting each other, learning from each other, etc - no "prima donnas", and they all have fun doing it - it leads to a good day of work.
I'm lucky in that for most places I have worked - from the first shop that took me in, to my current employer - this has been the case. I can only think of a couple of places I worked where that wasn't entirely the case; both came with excess politics, and other stress that I just didn't (and still don't) understand. I stuck out with it at both, but I'm glad I'm no longer a part of either.
One thing I do know and understand - this comes from someone who started their software engineering career when they were 18 years old, and now I'm pushing 50 - every place I have worked that I have had this "good team quality" has been a small employer, usually with fewer than 50 employees. My current position, there are fewer than 20 employees.
No - I don't make, have never made, and likely never will make "FAANG" money - but I'm not stressed either, and I make enough to keep a roof over my family's head, the lights on, and food in the pantry. I'm content, and if an opportunity comes up for a FAANG-money type position - I will have to look long and hard at it, before making that leap - because I feel that it might come with costs that just don't make sense to me any longer. I'd rather have a more "basic" salary and little stress, than a lot of money but stress out the door due to a myriad of reasons in such a workplace. That isn't to say that's inevitable, but I've just found that as the employers I've worked for were larger, the less my satisfaction with going in and the job overall.
> Companies want cheap, throw away talent.
I've read and heard about this, and I think it's probably true in many or most cases, but I haven't had this problem in my career.
I'm better compensated now than I ever have been, and when I want to move, it's easier than ever to get a good position.
A little bit of context: most of my professional career was in the south and midwestern US, but the last decade has been in the San Francisco bay area. Also, while I've always been a software engineer, I've always worked more on the 'operational' side, often called 'devops', 'SRE' or 'production engineer' these days.
I wish you the best going forward.