Optimizing your talking points (2018)
rachelbythebay.com
rachelbythebay.com
I've often worked solo, but have been on teams where I've written code that was... not great. Worked, but... suboptimal. Various reasons, but it is what it is. To remedy that, I would try to refactor old stuff in conjunction with new work. That was often rejected. So... I'd take to documenting needed refactorings/fixes in tickets. Those would rarely ever get attention - generally deprioritized or ignored. This led to - for me - constant low-level frustration. When working solo, I can prioritize what I need to; in teams... you can't ever make a suboptimal decision because it will live forever. Or until a 'system is down' moment. Those would lead to "post mortems", in which I would point to tickets requesting to fix ticking time bombs months earlier, explain they were ignored by leadership, and... that came across as 'blaming' or 'antagonistic'. The 'fix' is to just never write suboptimal code, which leads to more frustration and anxiety when writing.
Secondly, in 2017, I got a call to fix something I'd written in ... 2003/2004. That code was still in production (with minor patches by others along the way). It's quite humbling to have to review broken code and corners cut, and realize that you were the one responsible for it (and no one else). That (and a few other incidents) have given me a big change in perspective on writing maintainable code (and documentation, etc).
But yeah, the experience of having somebody asking you "Hey, you know about X! Do you know anything about this system here? What am I doing wrong that my program always gets a different result?" when it's your code, it's because your code was always obviously wrong, it's the first you ever notice it, and that person's boss is complaining because their code is correct... It's not nice.
:-/
My foodservice days had "if you got time to lean, you got time to clean" drilled in to me, but it's not always the same in software. What constitutes "clean" may be the core issue.
2) Codify norms of how a shared goal is worked on
2a) refactor tests as part of separate PR
2b) realign code with refactoring in mind (this is the begin transaction portion)
3) commit work
4) merge everything into main
It might take 3x longer, but it is more controlled.
The larger the team, or the more consumers, the more important it is to get the interfaces right. And if you can refactor the interface ahead of the code itself, the refactor isn't even noticed.
- Developers were encouraged to put in time to maintain and refactor code. (including forcing them to take time to focus on that and do nothing else)
- Engineering-centric work was prioritized over random product management asks.
- Schedules were adjusted to make sure the engineering work is done properly.
I'd say this was my typical experience, including S&P-500 multi-billion dollar companies, 100M-$1B companies, startups. I would also say that in all these cases there were experienced software engineers and managers that could be trusted to make reasonable tradeoffs and also pay attention to business needs. Often engineers interacted/worked directly with customers.
There has to be balance and that balance is typically achieved through people that can apply a balance. Striving for "perfect" can lead to never ending refactoring and never shipping. Ignoring technical debt or shipping garbage can lead to the collapse of the business over time. Neither of these extremes are the right thing. Where exactly you land on that spectrum also depends on the specific product, industry, customers, business.
We are all time travelers. We are kind to past selves and slightly disrespectful to future self.
Past self - so young, naive but productive! He did so much. At the time it took too long, but looking back, what mountains were climbed! It took me two days to figure out the code, but in the end it was pretty clever. Present self must have bad memory if he forgot it all
Future self - he will right all wrongs. He is older and wiser. He has infinite time. Time to refactor, to replace the XXXs and TBDs with intelligent code. to implement to good ideas and re-implement the mediocre ones.
with better comments, maybe all of them will become one.
A perfectionist attitude stands in opposition to this - just try harder and stop making mistakes. There's nothing to learn, just more individual effort to apply.
But that's fine. If I have a reason to change it, I'll clean it up. Until then, it stays around as an example to show some bad practices and why other approaches are better.
Once I ate a small fuckup from one of my juniors (we put a wrong software version in a report), and instead of fixing it with the client by simply saying "we had a mistake, here is the fixed report", my superior only could think about "could we hide this, and keep the face that we are perfect?". Of course, this same person takes any mistake from other people as an opportunity to ask for discounts, compensations and freebies.
I've taken to responding with: "Because you probably have more IQ points than me. I have fewer IQ points than you, so therefore I must do dumber and simpler things than you."
It's made some of their faces turn red in embarrassment, as they finally realized what unreflected belittling little dorks they were being.
This means they can't shame / guilt you for doing something suboptimal and I believe this is often their goal - establish superiority by inducing guilt or shame.
It's like opting to not play the game with them. And usually, that's the winning move.
Unless you're being totally earnest, this one reads like "I'll take it under advisement"[0]
[0] - https://getyarn.io/yarn-clip/ed82da6b-db48-49aa-a105-f190e63...
> given choice between complexity or one on one against t-rex, grug take t-rex: at least grug see t-rex
The second question seems like the type of feedback that would usually be fine. People's skills and knowledge don't always overlap. What is crazy complex for A may not be for B and what is crazy complex for B may not be for A! And that doesn't have to have anything do with A or B being smarter. A might not know SQL and B might not know pandas. But sometimes it really does make sense to move some code from SQL to pandas or vice-versa (assume for the moment that both SQL and pandas are already in the tech stack). Some people find it simple to write in object oriented style and others in a functional style. What makes more sense to do is not always obvious. So the question could be a good one. If the suggestion is bad, explain why it's bad. If the suggestion is good, maybe consider if it's worth doing at current point. If it's somewhere in the middle or there's no time, acknowledge and move on.
And when I’m on the other end of this asking someone else why they didn’t do it in some way that looks obvious to me, I try hard to avoid “why not just”. Sometimes I will ask “I assume you didn’t X for some reason?” But maybe the best is to ask why nicely without making any suggestions.
When the question comes because they were lacking context, this can sometimes be headed off at the pass by announcing why the most obvious things didn’t work before explaining what you did do, or by highlighting the confounding requirements or problematic inputs. If the question comes from already-committed code, the goal would be to have commit or MR code comments that prevent post-facto second-guessing. Sometimes it’s useful to accept the question without retort and just answer it directly, by explaining that their idea was tried and didn’t work, and what the reasons are, and ask if they’d like to share any other ideas, earnestly not sarcastically. :P
If the suggestion really was something I didn’t think of and seems like it might solve a problem, which might be rare but does happen to me on occasion, then I do like to tell them it’s a good idea and recruit them to help me implement it. In that case, pushing back on their assumptions or tone is tempting to me, but I will try to let it roll off and just take the feedback and be momentarily embarrassed.
The first character wishes to remove the fence because they don't see a good reason for it. The second takes a different approach: first show that it isn't necessary, then remove it.
Plenty of things are made useless over time. But there are also lots of things that look useless but aren't. We don't know, a priori, which is which, hence the need to be cautious.
(That said, I think there are also cases where ignoring Chesterton, removing the fence, and seeing what will happen is the best option. It just requires good planning and good testing so that you can be confident that a bull doesn't suddenly appear out of nowhere!)
Always, always assume this is the case - it might frustrate you to no end, but until you have conclusive evidence something is "wrong", it's best to ignore it and toodle along with whatever you're supposed to be working on (I always encounter these head scratchers when working on legacy code, my tasking being something unrelated).
e.g. if you have 10 items to store, then a simple file may be a pragmatic choice. When it grows to 10,000 items you may need a database. But if you started with a database for just 10 items, people would complain it's overengineered.
If you have 2 classes, an if/else can do, but at 20 you need some Factory pattern, which would be an architecture astronautics if done from the start.
And when you try to anticipate such growth, you'll create overcomplicated code whenever you guess wrong.
A continuously developed project will systematically keep outgrowing itself.
It's good to learn from our mistakes. But if there's one thing I have learned from working across teams and orgs, it is that basically everyone works with imperfect information. And oftentimes, you just have to make do, write the code, and try to make room to course correct in the future.
> When it happens I update the post to link to the nasty comment, without judgement, just to shine a light on it.
Not a bad idea. Not always possible, if the comment gets dead'nd. In any case, I do not respond in kind. I'm quite capable of it (recovering troll), but I won't go there. It's not being a "snob." It's just that I've learned that gasoline is an ineffective fire suppressant.
If I'm wrong, I've learned to promptly admit it; in the same venue as the mistake (a pet peeve is private apologies for public attacks).
There is a line though. I feel that I do really good work. I've been doing this for a long time (like, 40 years), and have learned quite a bit, in that time. I've also worked some pretty tough rooms, and for folks that wouldn't accept crap, so I have learned to habitually do decent work.
My general policy is to avoid casting judgment onto others in public. It doesn't help; even if I'm right (not always the case).
But if we're working together, or I am using your stuff, then it might be a different story. I have had people savagely attack me, because I won’t accept garbage. Guilty as charged, but I don’t go Torvalds on them. I just tell them that their work is not acceptable to me, in a respectful manner, if possible.
Nevertheless, I have found that I can always improve, and learn new stuff; sometimes, from the most unexpected places, and being open to these lessons is basic good policy. I become right, by being wrong, and learning otherwise.
"Good judgment comes from experience. Experience comes from bad judgment."
I’ve seen this pattern play out over and over. It makes what could be a great lead senior engineer just a lone wolf only a few people want to work with.
> feel that I do really good work. I've been doing this for a long time (like, 40 years),
Never substitute tenure for competence, particularly when you are convincing yourself that you do good work.
One of the biggest red flags in hiring is when people defer to tenure as a reason for anything technical. It is very easy to do things wrong or poorly for a long time without even knowing it. So falling into the trap of “I’ve been doing this 40 years and people have paid me for it, so it must be good” is a death sentence.
The funny thing is that if someone has been doing IT for 40 years, I'd expect them to be generally aware that they might be good at big picture stuff but less so on minute things, as technology, philosophies and approaches change every few years but the general concepts stay the same.
You can take it as feedback or not, as you said, it's a free country.
But be that as it may, I don’t “harsh out” on people; especially in public venues. I may think "garbage," but I'm much more likely to say "this won't fit into the framework in that form." It’s my experience that many of today’s folks get very nasty (and personal), when confronted with even mild rebuke. I can understand why Torvalds goes nuclear, although I won’t go there, myself (I consider it unprofessional).
I remember once, denying a patch (SVN), because the "fix" would have addressed the submitter's particular issue, but also would have broken the functionality for, literally, hundreds of others. I told them that it was a good idea, but I couldn't implement it, as provided, because of that, and suggested that we figure out some changes.
The response was a long, public excoriation, complete with genealogical evaluations of my ancestry, back to the Pliocene.
I decided that, even though they had a point, and we probably could have figured out how to give them what they wanted, after some give-and-take, it wasn't really possible, because of their attitude. I did end up applying part of their request; just not the part that broke it for everyone else (I did credit them in the comments). I blocked them, and we have never worked together since.
I remember a post here, some time back, where a fairly talented young chap, was complaining about not being made a core Linux Kernel contributor, simply because he submitted a good PR.
If we want to be above-average, then we need to be willing to put ourselves into positions, where we will get criticized; and, quite frequently, the ones doing the criticism are far from gentle. It's been my experience that folks at the top of their game, frequently fail to accomodate those that are not at their level. They aren't always right, but they are often worth listening to, anyway, and we don't do ourselves any favors, by reacting badly.
There is definitely something to be said for earning our stripes.
You know what the great thing about years of experience is?
It's usually "I hold this $TECHNICAL opinion because it is the result of careful refinement over 20 years."
In some cases it is "I formed this $TECHNICAL opinion 20 years ago, and haven't come across enough evidence to change my mind"
It is VERY RARELY "I formed this $TECHNICAL opinion 20 years ago and dismissed any evidence to the contrary over the last 20 years, while still managing to retain gainful employment".
TBH, if you are seeing people from the third group often enough to use it as a heuristic, chances are it's a poor (or poorly correlated) heuristic that you haven't yet seen for the poor quality it is.
IOW, you are holding an opinion based on your experience, about others who hold an opinion based on their experience.
Holding on to this opinion might even make you part of that third group I listed above.
Very ironic.
I have never encountered someone who just said, “I don’t do X because I have 30 years of experience and know it doesn’t work” who was able to technically justify their reasoning. It’s always a red flag.
It’s no different than someone who tries to use their rank as a reason for something.
> IOW, you are holding an opinion based on your experience, about others who hold an opinion based on their experience.
>Holding on to this opinion might even make you part of that third group I listed above.
>Very ironic.
You’re really struggling to grasp the point or you don’t know what “ironic” means. Basing opinions on your experience is fine. Basing them on length of experience is absolutely not.
The world changes very quickly, especially software. The older an opinion is on a particular architecture, technology, etc is, the less it should be trusted, not more.
Honestly, I've never met these people you meet all the time. I'm sure there are developers who have 1 year of experience repeated 30 times, but I assure you that you are more likely to win non-trivial money in a lottery than to meet these people.
And do you know why? Because
> The world changes very quickly, especially software.
The developers who are still programming in COBOL, with no source control, for mainframes that don't even physically exist anymore, are rare.
> The older an opinion is on a particular architecture, technology, etc is, the less it should be trusted, not more.
"Throwing more people at a software project does not make it proceed faster".
Here's the thing - you're using it as a red flag. But your usage is itself a red flag.
I dunno if it does much to discourage such comments, but there's something to be said for a metaphorical dunce cap for people who engage in that sort of discourse.
This article is an interesting companion to "No more pink mustache" [1] wherein Lyft is described as "broken at a scale that is hard to believe" - often the explanation for quality is the org, not the human in the chair :-)
What strategies do people employ here?
Three options:
- Give up, cede the ground, and move on with your life. The less sleep you lose over how unfair it is, the better.
- Confront them head-on. They are ready for a fight, but their position is inherently unreasonable. The less you get dragged into their headspace, the more you "win".
- Come down from above. Bring social proof that they are wrong into their space. In the OP, this would be programmers who mutually respect each other's work, and are productive without nitpicking.
The person offering the advice may be an idjit, just at dealing with others or maybe even completely.
It's OK if the some of rest of the world fails to agree with you. People voicing contrary opinions, failing to agree with you, etc; doesn't threaten you in any way.
These people usually think there preferred feedback is the best way so therefore everyone should feel the same way and if they don’t the other person needs to change.
They are of course wrong. But if you tell them this, they demonstrate why I use the word “most” in the opening sentence.
Too true! I find it helps if I think of it as an engineering problem: "what can I say that will make these people not commit the same error again?" A bit dehumanizing and manipulative, but can be super effective at shifting away from blaming and belittling (almost never works), and towards mentoring.
I'm reminded of a Simpsons episode where Homer tries to assemble a barbecue by pressing a brick and a piece of pipe together.
So easy to program defensively in C.
Certainly all the most experienced engineers I work with, who should definitely know better, still haven't fully internalised the fact that all code is broken.
Even most Hello Worlds don't check the pipe was written to correctly. And now we get into "well actually that's technically not a bug because it is not in the spec" and if we're finding the need to split that hair, we can hardly be talking about some mythically perfect software.
“The reward for coding errors found in Knuth's TeX and Metafont programs (as distinguished from errors in Knuth's books) followed an audacious scheme inspired by the wheat and chessboard problem,[10] starting at $2.56, and doubling every year until it reached $327.68.”
They're features!
The word for this is not "perfect", but "overengineered"
"Every program has at least one bug and can be shortened by at least one instruction -- from which, by induction, one can deduce that every program can be reduced to one instruction which doesn't work."
I was a `perfectionist` for a while due to certain bad experiences at work, and it was only through the help of really good teammates that I was able to slowly get rid of it. And that required pointing out things like what the author has done in their blog post and once someone sees that mistakes are things that anyone could make, they get more comfortable the concept.
The harder part is understanding why a perfectionist is so, and then not getting frustrated while you try to help them improve.
He did also not want me to do any testing as "the customers were better at finding bugs than we are"
He's not wrong about that quoted bit, though :-/
Paying customers are uncannily better at finding bugs than anyone!
[Note: I am not advocating for removing testing from your process.]
Nobody's perfect, but there are ways people can get better. Or just take advantage of tools that can help automatically catch these sorts of errors. This is precisely why people create regression tests and set them up to run in the CI/CD, to reject changes that break them.
As for being less of an asshole, no shortcuts with that - just exercise your empathy, put yourself in their shoes, take a deep breath, then go to bed. Tomorrow morning, if you still feel the need to pen a blog post, maybe write out a technical solution without assigning blame.