6 days to change 1 line of code (2015)
edw519.posthaven.com
edw519.posthaven.com
That should be the point of push back “Great feedback, and appreciate the direction to improve code quality, however the implications of changing Y means we need X, Y, Z approval and it will many days. I am making a tech debt task with what you described and will be done in a follow up PR based on priority and bandwidth.
Let’s focus on what it would take to get this surgical PR out.”
The biggest lesson I learned is to make focused PRs, and learn to pushback when reviewer asks for a scope creep. Mostly other engineers have been pragmatic.
It’s unrelated to number of lines as you can reformat while codebase but not change anything logically, or change some feature flags which could have a huge impact. But ONE FOCUSED CHANGE AT A TIME
I don't agree. IMO, the worst issue being displayed here is that of the "6 days to change 1 line of code," almost half of them elapsed before an engineer ever looked at the issue. If this is such a high priority issue that the company would "need" (scare quotes intentional) to do a layoff if it's not implemented soon, those 2-3 days before anyone looked at it should never have happened. And that is apparently what passes for "the fast track" in this development process.
And then there's the 2 days at the end of this 6 day period where it looks like nothing happened, because the test plan was deemed insufficient.
"If you change this, you also have to fix other pending issues" only took up 2 hours here. There are at least 2 or 3 other things I could fill in here that I'd flag as core issues with this process before I'd even think about dealing with this part of the process.
It should have been some VP realizes how important this is. Gets the security folks, testing folks, Senior devs, team manager in a room and task them at figuring how how to solve this very specific problem before it impacts a layoff.
I didn’t really understand the difference between good and bad management until I had multiple different managers and VPs over a decade at different companies.
The difference between good and great is night and day once you witness an exemplary communicator who can get the right people together and give them focus.
I’d rather create issues silently so I don’t forget instead of even adding a FIXME or TODO. I think this part of reviews is broken. Resolving tech debt should not be a requirement for completing a task, it should be planned.
Such tasks will never be planned because there's always higher-priority tasks to be done. I actively encourage my developers to clean up the code they'll be working on, otherwise you're just piling tech debt upon existing tech debt.
The only exception is repository-wide refactorings: if those are necessary to implement a feature, we block the feature and create a prerequisite task outlining the refactoring needed. But this is mostly to aid the review process, in my mind these two tasks are still one (and if I work on it myself, I usually already have the feature half-implemented so I can double-check that the refactoring does indeed make the feature easier to implement).
While I broadly agree on the boy-scout rule, it can severely throw out (already poor) estimates.
It shouldn't be a rule ("always clean up the shit you see when working on something else"), it should be optional ("If it doesn't mess up your original goal, clean up as much as is possible within the estimated time").
New rules are added, and the automation adds rule override comments to every existing violation - which also lets you track them. When you need to rush code out that needs to violate a rule, you add an override comment as well, with your name assigned to fix it.
Then over time, you build a culture that wants to fix these rule violations separate from feature development.
Whenever that happens just add a TODO ticket. Unblock production and the system is not worse for it
I dislike excessive usage of these kind of tools because not infrequently you end up making your code worse just to satisfy some dumb tool.
The real solution is just accepting that not all code needs to be like you would have written it yourself, and asking yourself "does this comment address anything that's objectively wrong with the code?" A lot of times the answer to that will be "no".
Unpopular opinion: I think individualism showing in code is a bad thing. Code should be textbook boring with as little personality showing as possible. This, of course, is due to my experience working in a department with ~40 developers. I work so much faster when I don't have to decipher "clever" code or somebody's personal style for how to line break their over-complicated comprehensions. It slows everybody down when there are 40 different dialects being "spoken". Homogenizing our code with linters and formatters means that any part of the codebase I jump into will look completely familiar and all I have to do is focus on the logic.
I don't do much Python, but when I do I've often run in to line length "linters" for example. I (strongly) prefer to hard-wrap at 80, but if your code happens to end up at 81 or 82 then that's fine too, and sometimes even 90 or 100 is fine, depending on the context. Unconditionally "forcing" a line break by a linter is stupid and makes the code worse 99% of the time. It's stuff like this that serve little point.
And if you need to constantly tell people to hard-wrap at ~80, employing common sense, then those people are morons or assholes who should be fired. It's a simple instruction to follow. (and yes, I've worked with people like this, and they either were or should have been fired).
Actually I found that the number of linters is directly proportional to the quality of the code: the more linters, the worse it is (on average, there are also excellent projects with many linters). The first reason is that people will make their code worse just to make the linter happy, and the second reason is that I found that linters are often introduced after a number of bad devs wrote bad code, and people think a "linter" will somehow fix that. It won't: the code will still be bad, and the developers who wrote it are still writing bad code.
Linters/static analysis that catch outright mistakes should be added as much as possible by the way (e.g. "go vet": almost everything that reports is a mistake, barring some false positives). I'm a big fan of these tools. But stylistic things: meh.
The real advantage of linters is that code comprehension becomes easier and authoring that code becomes simpler. The code always follows the same style in every project that team has, and everyone can configure the linter to reformat on save. It also completely removes the conversation on style from code reviews.
Haven’t you ever gotten a big PR from someone because their editor settings were different and they auto formatted a file differently than it was written before? This makes PRs a nightmare to differentiate between style and substantive changes.
The auto formatting is honestly one of the biggest productivity gains as a developer that I’ve seen. No longer do you have to ensure your code is indented when typing. A lot of times, I will even write multiple lines of code on a single line and let the formatter take over. And the end result is that my code is consistent and matches the style of all the surrounding code. It takes a cognitive burden off of everyone, when writing the code and when reading it (PR or otherwise).
I immediately reject those PRs. If your editor can’t format only changed lines you need a better editor. If you’re working on a task, changed lines should only be for what is necessary to implement it - nothing else.
That said, any autoformatter will need to strike a careful balance or it will produce nonsense: too little enforcement makes the tool useless, and too much will just crapify things. gofmt mostly gets it right, but I've never been able to get clang-format to produce something reasonable. I don't know about Python, as I don't do much Python.
Because of this things like [`eslint-config-prettier`](https://github.com/prettier/eslint-config-prettier) exist to ensure conflicting eslint formatting rules are disabled if they can be handled by prettier.
It's not about whether it's automatic or not, it's about the code being worse (that is: harder to read). Breaking lines because it's 1 character over some arbitrary limit is almost always bad, whether it's automatic or manual.
Code style is the epitome of bikeshedding. Anything consistent is fine, and using a tool to automate that is a huge productivity win.
132 is fairly reasonable but I can still skim-read 80 column code noticeably faster (especially when I'm looking at a side-by-side diff).
You're welcome to have different preferences, of course, but I came to using 80 columns from having previously written much wider code myself - and the width of the -screen- I was using had nothing to do with my choice to switch.
// fires the missiles.
// Spongebob case (and extra underscores) makes it hard to accidentally type.
void FiRE___MIsSiLeS(); // !!!!
// be careful!
void fire_missives(); // posts a witty tweet
After code review: void fire_missiles(); // fires the missiles
void fire_missives(); // posts a witty tweet
Code is more uniform, zero downsides!In an ideal world, developers care more about how their program works more than how it is written. But ya, unfortunately most people are working on applications they don't care about, so they get overly creative with code and tools.
If workaday code needs documentation for other developers to understand it to begin with, it needs a rewrite. Even if it runs great as code, people aren't computers and it needs to communicate it's purpose to both. Finding a showstopping bug under pressure in code like that is enough to make you want to put pencils though your eyes.
Also, agreed on documentation though I didn't feel like diving into that one in my response.
EDIT: Ohhhh I see now :)
'Workaday' technically has two definitions: the first is something work related, and the second is something ordinary, common, or routine. Both definitions carry connotations of the other though. In this context, I'm referring to the everyday code that we write to solve most problems. I'd juxtapose this with unusual code working around really weird constraints or making up for a fundamental shortcoming or bug in a language or critical library which might require janky counterintuitive code.
I can only agree with this if the lint rules are paired with 100% automatic reformatting, and not simply a lint rule that rejects the changes. It's a huge waste of time to force the author to go back and manually fix line lengths to meet someone's arbitrary preference for how long a line should be. Line length is clearly a preference and forcing everyone to conform to a single standard doesn't solve legibility.
The language should make line breaking obvious or automatic. IMO, The fact that it's an issue at all seems like a weakness in Python's syntax. Compared to the languages dominated by curly braces and the lisps with their parenthesis. Python saves my pinky fingers from typing braces and parenthesis but it demands more attention to the placement of line-breaks. Combine that with very short line-length standards and it leads to significant annoyance.
> Line length is clearly a preference and forcing everyone to conform to a single standard doesn't solve legibility.
I fully disagree here. Enforcing 80 characters is way too short for any reasonably complex code and leads to exactly the issue you're complaining about: tools doing automatic line breaking which make the code worse, AND/OR developers making their code more golfy in order to fit inside the line length limit whenever possible.
What you're arguing for (individual developers taking responsibility for their own line breaking style) would only work if every developer cared about such things, and now you have business/product complaining to project managers about how much time we're wasting formatting our own code by hand instead of letting automation remove that variable from the equation.
Again, all of these opinions are with the perspective of working with dozens of developers on a very large and complex codebase. If I personally disagree with somebody's "style" for line breaking, and I happen to find myself working in their code, what am I supposed to do if I personally find their code more difficult to read? Do I do re-work to make the format align with how I best read code? What happens when the original author comes back?
Developer ego is a huge problem. Automated formatting and linting help to reduce that problem.
EDIT: I was actually responding more to arp242... whoops
Making it a hard requirement is a bad idea, making it 'required unless you can give a really good reason' (and notice that arp242 made clear that lengthening some lines a bit was a perfectly reasonable thing to do) is usually* workable.
My usual coding style tends to fairly naturally fit into 80 columns, -especially- in the case of complex code because that tends to get broken up vertically for clarity, and an '80 columns unless you have a good reason' limit seems to work out fine for e.g. PostgreSQL whose source code I personally find -extremely- readable.
I do agree that a lot of the time having some sort of autoformatter that everybody runs is a net win, especially since with a little practice you can usually predict what the autoformatter is going to do and code such that the output is decently clear to read as well as consistent with the rest of the codebase.
(*) Enterprise java style codebases where every identifier name is a miniature essay less so.
Usually many architects tend to go overboard with interfaces for everything, repositories, data layers, hexagonal architecture, and whatever else is fashionable at conferences.
I'll only push for the better way if I, or someone else, is willing to refactor the whole codebase.
Last thing I want is to work on a codebase with N different ways to solve the same problem. That decreases productivity too much.
The less communication between devs during code reviews - the better. It's exhausting to be diplomatic to your coworkers asking them to change something. It's a minefield full of feelings and egos.
Of course, if all you care about is the fungibility of your programmers, then having those overly strict rules completely makes sense, but if you want to produce a quality product, not so much.
I wish there was something like semantic commits “fix/feat/chore” for review feedback, specifically a keyword for these little things that are more future advice than must fixes.
I also try to be clear when I don’t expect to do a second review if they make the minor changes, that the green check mark carries forward.
More. broadly I’ve been trying to favor “rough consensus and running code” in my PR reviews, even if I don’t fully agree with an approach I’ll give the writer the benefit of the doubt since they’ve most likely spent more time thinking about the problem than I have. Or at least that’s my hope!
Nit: This is a minor thing. Technically you should do it, but it won’t hugely impact things.
Optional: I think this may be a good idea, but it’s not strictly required.
FYI: I don’t expect you to do this in this PR, but you may find this interesting to think about for the future.
None of these block a merge and anything beyond these type of comments will be a in-person discussion.
The FYI tag is a fantastic idea and I shall try and remember to use it in future.
This is all well and good until your company brings in automation to enforce the setting that all changes dismiss reviews on all repositories.
Combine it with the requirement that all branches must be up to date with master before merging for the double whammy of rebase/review/repeat hell.
The other important benefit is catching stupid mistakes - formatting, missing code, > vs >=, etc - dumb mistakes that everyone makes. But ideally most of those mistakes are caught by types, tests, and linting, so the code review just makes sure that a different pair of eyes has sanity checked things. If code reviews become mainly about this sanity check, then it's often a sign that the types, tests, or linting are inadequate (or that someone is being too picky).
The other problem is when reviews too often focus on the big problems - architectural discussions about how to implement a feature - in which case there's usually a need to have more architectural discussion before implementation starts.
You just can’t do that async inside a GitHub PR to the same level.
If that is truly the goal, shouldn’t the programmer have that information before they start writing code?
> The other important benefit is catching stupid mistakes - formatting, missing code, > versus >=, etc - dumb mistakes everyone makes.
I’d love this to be true, but I’ve now seen so many bugs missed in PRs because the reviewers get bogged down in “code style” feedback (which is this generation’s commas versus tabs debate I swear) that they completely miss the more severe issues. Additionally, the reviewers often only have shallow knowledge of the business requirements and can’t know whether > or >= is appropriate.
> The other problem is when reviews too often focus on the big problems - in which case there’s usually a need to have more architectural discussion before implementation starts.
Totally agree here.
To be clear, I support the idea of feedback from other developers during the development process, but I feel that little thought is given to (a) what kind of feedback is truly valuable, (b) when the feedback should happen, and (c) who is in a good position to provide that feedback.
> If that is truly the goal, shouldn’t the programmer have that information before they start writing code?
Could you clarify that a bit?
I agree that programmers would ideally start out with some knowledge of the codebases they work on, but by working on the codebases, that typically make changes and so that knowledge is quickly out of date! ;)
That's the value of code review as knowledge sharing - as new things are implemented, or old parts refactored, or new technologies introduced, or even parts deleted, multiple people are involved in those changes and so gain that knowledge.
EDIT: and I completely agree with the rest of your comment! Giving good feedback is a learned skill, and too often we don't put the time in to learn (or teach) it properly.
Again, this isn’t the “fault” of the code review, it’s that there are insufficient or missing pieces of the software development process overall. Yes, having a code review is a good thing, but we often try to make it do all the things.
One of the big things this achieved was that we rarely had to rewrite stuff, or come up with a solution that was missing some vital detail. Because everyone was involved in the initial plan (UI, backend, and business), we had a good grasp of different people's needs and could challenge ideas that would cause problems in some niche use-case.
To me, implementation and code review both come after this architectural discussion. That's not to say that there aren't still decisions to make, and sometimes I'd still sit down with the other UI guy and discuss how we might best structure our code - but again (ideally) before and during implementation, rather than after it when the branch is ready to be merged.
Rather, I see code review as a chance to learn about the minor details of implementation. For example, a function to search through a list of objects might have a dozen different potential signatures, invariants, and usages, depending on who implements it and how they prefer to work. Having a review makes sure that both (or all) developers know how to use this function, and have seen it if they need to use it somewhere else in the codebase.
And sometimes none of this works out, you think you've planned everything, you write your function to search through objects, and your colleague points out that a standard library function can do everything you've written but simpler and faster. And then you'll still have to rewrite your code, but now at least you've learned something new.
But there's also very real issues that one person thinks is a nitpick that really isn't. Perhaps because they can't see the issue with their own eyes, they don't understand the issue or they lack the ability to leave feelings aside and rethink what they've written.
We've all been attached to code we've written. We probably think it's the most elegant code ever written. But sometimes you've just gotta admit you were wrong, it's not readable or it's flawed and it will be worse off for the codebase.
I've also been called a nitpicker by someone more senior than me for pointing out some very real and potentially problematic race conditions in their code. To me, a race condition is a fundamental issue with what has been written and should be fixed. But to them it was acceptable because they hadn't seen it break naturally yet.
You can use code formatting and linting tools to automate the low hanging fruit but there's still opportunities to offer feedback that could be considered nitpicking but IMO isn't.
For example variable names, breaking up long functions, not enough test coverage which hints maybe the author didn't consider these cases or changing this type of code:
if not something:
# Unhappy case
else:
# Happy case
To: if something:
# Happy case
else:
# Unhappy case
If you have 10 devs working on a project you're going to get 10 different ways of thinking. If you're working on a 10 year old code base with a million lines of code and you don't address things that could sometimes feel like nitpicking then you wind up with a lot of technical debt and it makes it harder to work on the project.I like when people comment on my code and find ways to improve it in any way shape or form. I don't care if they have 5, 10 or 15 years less experience. I treat it like a gift because I'm getting to learn something new or think about something from a perspective I haven't thought of.
if not something:
# Unhappy case
return
# Happy caseIt's mainly avoiding the "if not else" pattern in 1 condition. I haven't met anyone who fully agrees that it's easier to read than "if happy else unhappy" or returning early with whatever condition makes sense for the function.
if not something:
# Unhappy case
else:
# Happy case
To: if something:
# Happy case
else:
# Unhappy case
This is the exact kind of rule that some people feel needs to be applied globally and will run into conflicts with rules like "put the shorter case first" so people aren't having to keep multiple cases in their mind at once.In short it's a preference masked as a best practice, and putting it under the same kind of "oh we should change it for the boy scout rule" logic as things like "Maybe let's not have 1000 line methods" is the exact kind of performative review being complained about.
In my reviews, when I look at the tests, I put on a test engineer hat. Testers like to do things like give an empty value where one is supposed to be required by the business logic, a negative or other out-of-range value, an emoji or other wonky unicode in text. Just basic stuff to a test engineer, but lots of programmers only write tests for the expected happy path, and maybe one or two cases for common alternate paths. The most common failures I find are in handling dates and date comparisons.
I've been wanting to add more fuzz testing to the tests I write, but I haven't quite gotten my head around how to do it effectively.
- This won't do what you appear to be expecting it to
- This will prevent <some other feature we're likely to need> from being implemented; at least without a much higher cost
- This will work, but is very hard to understand; it will negatively impact maintenance. Consider doing it this other way, or adding an explanation about what's going on
- This code is ok, but might read/work better <this other way>. I'm not failing the review because of it, but it's worth keeping in mind for future code.
By completely removing any personal preferences and disagreements on style, the whole team just gets to hate on and berate an inanimate tool instead.
We all just seem to equally dislike flake8 and move on with our lives.
Yes, you can go to extremes, and some people are annoyingly nitpicky when it doesn't matter. But generally, code is often a liability, stuff that is hard to understand (or even potentially subtly wrong) will cause issues down the line, and so on. Code review helps mitigate these issues, something which I think is one of the few empirical results we actually have. Plus, it also spreads knowledge about the code base.
The submission is in any case not pointing out that code review itself is bad (or even that having to adapt to a new code style is the problem), but rather the whole bureaucracy around it. Code reviews are good when the turnaround is swift.
Because the projects that weren't built fast enough were eventually thrown away, meaning they never require maintenance, which is the source of the sampling bias you are observing. I've seen it happen in some cases (engineer with the wrong personality leading an R&D project).
Build a culture that prefers succinct, non-nitpicky code reviews. Static analysis tools only give reviewers more crap to nitpick.
Which static analyzer is this? Every tool I've used only finds bugs the are provable so the false positive rate is essential zero
That said, often teams don't give credit for code reviews, or take into account the (sometimes considerable) time required to write them. To some extent, tools are also to blame - I think all teams would do well to pick a system that integrates with the dominant IDE. Doing code reviews in the same space you write code just makes sense; requiring that you use a friggin' webapp is HORRIBLE.
But of course, it's very very important to ignore that feeling and do the sensible thing, which is be happy that the code review is smooth and the code can be merged. I can't imagine the existential dread of realizing that half your job is pointing out the same common errors every single time. Tools like clang-tidy, clang-format, etc are so vital for staying sane.
That said, I think culture for this kind of thing varies wildly between different companies, and between teams in those companies; many (most?) teams are comprised of small numbers of people, so even one team/technical lead having a preference for a certain style could change things, and... well, everyone's different.
1) O(N^2) in the hottest code we have.
2) O(N^3) from someone else in the same area.
3) Filling a cache on first access - this causes the system to page (high latency!).
4) Hunting for data themselves and creating null pointer errors.
5) Hunting for data themselves and missing all the fun edge cases.
6) Duplicating a feature that already existed.
I'm guessing (4) could have been caught by static analysis?
I nitpick only because it’s a clever turn of a word that deserves understanding.
I insist on doing code review in areas where static analysis tools are completely useless, like in SQL code: without context, any SELECT can be good enough to pass static analysis, but crash in production due to performance problems.
Nobody was ever promoted in my company for doing code reviews. None of the people that were ever promoted know how to do any sort or code review. I can say that the correlation between promotion and code reviews is negative.
For example, a field named "customers" that holds a single customer can be a major readability hurdle for someone who is looking at code for the first time. Even if you discount readers' annoyance and discomfort, which I don't think you should, a single field named "cusotmer" can become a drag on readability if the misspelling gets amplified in the codebase or if some programmers on the project aren't native English speakers. (It can be much harder to mentally gloss over language errors that aren't in your native language.)
Something I learned in school is that it's extremely hard to read something you've written as another person would read it. I had an English teacher that would split the class into pairs every time we had a paper to turn in, and in each pair, you would read the other person's paper out loud to them. The results were comical, and to most students entirely unexpected. Their whole school careers, they had thought teachers were being mean and nit-picky, until they got to see their friends struggle to read what they had written. Then they started to understand that a wrong word, a misspelling, a wrong verb tense, an ambiguous pronoun, could stop a reader in their tracks or send them down the wrong path trying to understand what the writer meant. They also learned that they could not see these issues in their own writing. When they read somebody else's writing, they would stumble over errors, but in their own writing, they had to make a special effort to see them, and even then, readers would effortlessly "discover" errors that the author had missed.
For many programmers, PRs are their first and only opportunity to develop this empathy for readers, and if they reject the feedback, they're going to remain forever in the dark about how other people experience their code.
Sounds like glorified and highly opinionated linters whom will just gatekeep progress because they “don’t get it”.
Wouldn't the top level overlords want better code review metrics? Padding your stats with comments that can be handled by static analysis makes such noisy metrics even more noisy.
Just implement whatever clean code guidelines everyone is keen in having, with their dependency injection guidelines of an interface for every single class, and move on with the actual work instead of burning discussion cycles in pull request reviews.
This is completely unrealistic, security teams would never respond so quickly.
But... The system improved in a few other ways:
1. The setting became configurable via the parameters table instead of being hard coded.
2. Auditing was introduced to track changes to that setting.
I'm not trying to defend bureaucracy, because I truly hate that aspect of large organizations, but just point out that additional value was created during those 6 days beyond what was originally set out to be achieved.
Incidentally, this is why you have to bake in a set amount of overhead into your estimates, and need to take this red tape into consideration if you do story pointing.
So your two wins were basically a "win" of not dealing with extra ceremony around code changes, followed by a "win" of recovering the functionality loss of the first "win" because future changes to this wouldn't go in the code.
OP: Please accept the 1 char PR, this is urgent. I just created a ticket to track the requested enhancements. Let's address production concern first then then I will get the rest after.
Reviewer: LGTM!
This is actually where seniority pays, if most of your engineering base can't navigate between rules and guidelines, the organization is crazy.
If a week won’t affect anyone’s jobs, follow the process or minimally alter it. If people are on furlough because of IT, you have everyone needed in the same room (physical or virtual) until the problem is solved.
We don’t have that context here.
But if Ed and the entire chain doesn’t have that context, That’s a system failure. The senior would likely just insist on a second ticket to fix it right after if he knew someone’s rent check was on the line. (And if not? That’s also a management issue to solve.)
The urgency of this problem was not communicated broadly enough and the impact of the simple fix was not communicated back up the organization so that it could be prioritized correctly.
It seems like Ed is just being "helpless" and blaming the organization when maybe he could have raised the issue back up to the president saying "my 1 line of code fix to your problem is being blocked by these people. Can you help?"
This was a communication problem as much as anything.
Which just states the fact.
> The system improved in a few other ways
Which were not required.
> Which were not required
Sure they were not required by Ed, but they were required by other stakeholders who are responsible for testing and maintaining this system.
I agree though, it would be frustrating to get into this sort of "yak shaving" situation where you don't even care about all these other requirements that are being added.
Like I said in a sibling comment, this is really more of a communication problem on Ed's part, and maybe he could have neutralized all these problems with better communication.
I could image a scenerio where somebody stored the number of months of backlog as a 2 bit value. 0, 1, 2 or 3, you know, to be smart and clever. This may not appear as a problem during testing because it may be hidden many layers down, in some downstream service that is untested. Maybe in some low code automation service....
Changing it to 4 would mean the backlog is 0. Who knows what the consequences might be. Would that service go and cancel all jobs in the production queue? Would it email all customers mentioning their stuff is cancelled?
I get that this is a seem gly easy change, but if a change of policy is expressed to the software team as an urgent problem, this seems like the management team needs better planning, and not randomly try to prioritize issues.....
They actually increased risk by insisting on refactoring a bunch of nearby things as the "cost" of the change.
"Fixing preexisting errors that violate new company policy" also arguably involves real risk reduction; you gotta do that work sometime, and if everyone in the company agrees the time is now, the best time is now.
Using Marge instead of Homer is not "risk reduction" but presumably testing accounting close is also critical.
Tony's request is also reasonable, unless you want to leave the next dev in the same shithole you were in re. the wiki state.
Now that is truly increased risk.
You can't just stack up a bunch of aphorisms and delegate your thought to them, some situations have context.
What constitutes "rushing through" a refactor, and what forces and context make it bad to do so? What can we do, if anything, to make it so that refactoring is as much a part of everyday development as the CI/CD process, and thus becomes just part of the work that's done, not something to be put off until the business decides there's nothing else with a higher priority?
That change should be shipped in isolation. With manual testing to cope for the lack of coverage, presumably. Refactoring doesn't have the same urgency as keeping the factory running, no matter how much we all believe in keeping the campground clean. It can wait until Monday in this particular case.
In the normal course of business, it's a different conversation. Even then, if you're making some poor dev refactor a bunch of code because they had the misfortune to touch it, maybe you should have done the work yourself a long time ago. Or written a linter and ticketed owners.
You don't want to make feature development some sort of pain lottery.
In practice, your approach often turns into "junior engineer abuse" where they have to clean up a bunch of unrelated pre-existing stuff to make the seniors happy as a condition of shipping their feature.
IT should have volunteered the info regarding how far back in the backlog this was classified as soon as that prioritization was made. "Behind 14" and with many people on the testing side occupied is obviously not going to help with "layoff level priority".
To me, the classification of "enhancement" just doesn't seem to capture the urgency.
For a time-sensitive and critical update to core functionality, the director of operations should have been aware of the mean time to deployment for the software and put together a team to fast track it, instead of entering it into the normal development pipeline with a high priority.
It made me laugh! And cry inside
I'd recommend a process where comments are allowed but reviewers cannot block commits. Each developer is trusted to be careful, make such changes as are pertinent to the task. Use CI as well and depending on the team it can all go very well.
I’m torn about blocking. I do get the sense that it’s frustrating to get that big red block, so in many cases people ask for changes without blocking - basically a “soft block”. But I’ve dealt with plenty of cases where a PR is so far off the rails (usually a jr. developer), I think it’s appropriate to send a message.
But there are some other developers who seem content to just routinely (not just sometimes) ignore anything that is not phrased as a command (such as "I think we should test this better"), and I've adopted the habit of not approving such PRs immediately.
This company leader is willing to lay off factory worker because of 10% under utilization, he can tweak some variables to increase productivity but ultimately the choice is either full utilization or unemployment. He can do this largely because, I assume, these workers are replaceable and can be rehired during busy season and because the profit generated per employee doesn't allow for any inefficiency.
I work as a software developer. Our under utilization has to get well over 90% before anyone is even considering getting rid of us. Many of us are putting in four hour work weeks. No one manages our minutes, our bathroom breaks, etc.
We are in a period of major capitalization of software. It won't last forever. Eventually the major infrastructure of the IT world will be built and the industry will shift to a maintenance mode. Most of us won't be needed, we will become replaceable and the profit we generate in maintenance mode will be insignificant to what we see today.
Factory workers are usually fired within minutes or hours of detections in low productivity of an individual worker. In our life time, I believe this will start happening with software developers.
That's exactly the difference. The factory is a system of processes designed to remove decision making and variation from each person.
You have to evaluate the degree to which that could be done with your skillset.
> in a period of major capitalization of software. It won't last forever.
I agree with your basic point-- not every company needs engineers developing novel software all the time. It's more of a boom and a bust creative venture, like producing a movie. If you choose to work in development over IT you should accept that risk. But I don't see why this has time has to be the peak.
No code review worked very well given the objectives of the team. It was an R&D group who's primary objective was "demo the nifty new thing to the executives". That meant a lot of short notice requests but also a lot of throwaway code. We'd demo the thing, the exec would be like "looks great, no business case" and the repo would never be touched again. Of course, every now and then our thing WOULD get productized and the downstream team would be responsible for turning chicken-scratch code into something production worthy. Those guys hated us with a burning passion.
Was a 2.5 year project, went live at 20 months in, was on time and meet budget with more capability than originally scoped.
Many days had 2-3 hours of discussion at the whiteboard. It was informal, didn't always involve everyone.
Oddly, we had three different pms during this project. We had a hard rule of no email or contact outside of stand-up with them. Two of the three pms were able to 'work' with this setup. The head of airport IT eventually realized after two years of this that we didn't need a PM.
We had a rule that if you are doing anything novel in the code base you had to have a conversation about it with at least another dev.
We all sat within a few feet of each other in a large private office with a huge whiteboard. We used index cards taped to another dedicated whiteboard for stories and if you couldn't describe the essentials on that, you had to break the story into smaller pieces. We were allowed to build our own machines and use as many monitors as we wanted. Was an Airport billing and tariff system for a large international airport, the accounting department head, director and other users were a couple of office doors away. They rarely missed a stand-up and they had an open policy for any real time questions. Standups were informal discussions, demos, question and answers not typically for status. The status update just took one glance at the cards on the whiteboard.
The final system improved revenue by 8% in its first and every following month. The director of Accounting was brought before the Airport Authority Board to explain. Billing disputes and adjustments with airlines went from nine days a month to one. The monthly billing workload went from 18 days to 5. Instead of a senior accountant being the primary user, they were able to offload this to one junior accountant with three years experience.
Bug rate was six production bugs, zero incorrect invoices in the first year live. I don't have any data after that.
The previous rewrite attempt failed after a three year attempt.
"Upgrade as you go" policies leave long tails of half-completed conversions that make the codebase harder to ramp new devs on. You'll also never finish the conversion because there's no guarantee that product focus will walk every part of the codebase with any regularity. Some product areas get left alone for years and years and years.
It's either important enough to cut over to the new policy in one concerted project, or it's not important.
They are relying on random unrelated work tasks to trigger these unplanned work time bombs all over the code base .
Either some new standard is important and the code should be updated, or not. Just relying on randomness and slowing down urgent work ain’t a plan.
Every process needs an escape hatch. Changing something which will prevent layoffs should trigger every escape hatch.
I started to participate in several meetings to explain that it does not use the cache system because bla bla bla. A week or two after a few meetings (and a lot of money spent), I got it deployed.
It's the same company that created a new meeting to discuss wasted time in all the other meetings....
At the time I thought: This is abnormal, but it is actually an extremely common scenario in many companies.
I've been in this kind of meeting. It was a 30-minute meeting instituting a rule that meetings should be 25 minutes by default.
VPs and managers droned on about how important it was.
Rule 1 in the training was to have a detailed agenda.
As far as I saw nobody ever followed rule 1 except myself and one other person.
I’m glad I work at a small company now.
all these have nothing to do with real life coding, it's more like a coding monkey stress test to me, you can only perform well by doing daily leetcode for months, it's geared towards young people who has those times to practice.
I recall the days I spent two weeks to add 50 lines of code to linux kernel, 95% of the time was to figure out how that kernel subsystem works and where to hook the code, but that matters 0 to nowadays FAANG interview process, the 5% of time for 50 lines code is all that matters.
The way ive always operated is that nothing in a Code Review can stop a merge unless its a rule written down before the review or its just a blatantly obvious incorrect miss of requirements or functionality.
I love seeing peoples comments about how things can be improved in reviews and learning new approaches or context, but if there's not reference to a written rule I should have known about beforehand anyway, I'm not changing it if I don't agree with it.
I've never worked on a team where code reviews worked that way for anyone besides maybe the team lead. Even if nobody uses the GitHub feature to add a blocking review comment, there's always this expectation that nearly every review comment has to be treated as "right" by default, even if it's ultimately based on opinion, and your job as the submitter is to either debate or accept every opinion before merging; this of course means a few changes lines can take days to get merged, unless everyone jumps on a call to have a synchronous code review, which nobody wants to do every single day.
The reality is most organizations don't write anything down, and even when they occasionally do, there's a high probability that said documentation is outdated. So while I like the idea of the written rule principle, I don't see it being widely adopted, and there are many more developers who actually believe it's better that every decision just lives in people's heads.
I do see people who seem to believe that, but they're always junior and it's all in their heads. Nobody ever said that you need to listen to every single comment.
Write good code, incorporate good suggestions, ship stuff fast, test well, deliver working software that solves customer problems. That's your job.
I don't think we need to over index on written rules for common sense recommendations like this. I'd be happy to see the first engineer blocking another's PR on the request. In the long run it isn't viable to optimize for shipping, I think a lot of the optimization has to be directed towards maintenance.
But at the end of the day, if you're on a team with somebody like that then you NEED written rules to deal with that nonsense and the Code Review process is the first step to identify it.
The nonsense gets merged the first time, but not before you add a written rule against it going forward. Problem solved.
I'm in the (perhaps enviable, perhaps unenviable) position of getting a small subset of my marching orders directly from our CTO. Engineering at my company is organized in such a way that, while engineers report to the CTO, product management (part of engineering) does not. When the CTO asks me to priority-override a new feature, or even a small change, I've sometimes gotten into arguments with product management over how this wasn't planned for, and how they need time to adjust schedules and collect requirements before I can begin work. Unfortunately, I can't use the "talk to your boss" excuse, due to that quirk of the reporting structure.
One memorable example of this was a feature request which came in hot in mid-June, which I had code complete later that day. We actually shipped it a few days ago. To product management's credit, they _did_ come up with requirements that were not met by my initial change, but I question whether releasing fast and iterating, or releasing correct after four weeks, was better for the customer.
Does your CTO (and whoever PMs ultimately report to) intend for these types of friction to occur every single time a CTO request appears? Does your CTO notice that these small changes takes extra time to occur? Does your CTO even care?
If the CTO and product boss are constantly stepping on each other's toes (or whatever), that's a problem that they either need to solve, just acknowledge as just the cost of doing business. And that ought to be communicated and acknowledged by everyone in the line.
This seems like it changes something with potentially super-high impact, 6 days from request by the CEO to release to production is a pretty good release time.
As demonstrated by the end of the scenario, the 'solution' was the president to more directly intervene.
The failure in this scenario isn't necessarily that the process got in the way, it was that when the President and IT Director kicked off the action, they were not fully aware of the efforts and overrides required to escalate to 'do this now'. A converse failure is that the intent of the President and IT Director was not properly communicated to all stakeholders in the process.
Lol, nah. This is fiction, no company IRL is going to start laying off people after a few days of noticing a small dip in production.
The whole premise of "We own this company but if this code change doesn't go through in X days we will fire people instead" is completely stupid.
But it is an entertaining story and it gets the point through that internal bureaucracy gets in the way of many things.
I like the description Jason Fried gave of policies being "organizational scar tissue" in response to a "cut" (i.e. something bad happening). He suggests that we don't scar on the first cut:
imul eax, [ecx+0x41], 0x10
Entails hundreds of hours of single-stepping through that opcode in Linux kernel using an indirect operand pointing toward its own opcode (self-modifying code).Even the extraordinaire Fabrice Bellard (author of QEMU) admitted that it is broke and did a total rewrite, which fixed tons of other issues.
Probably the code still works with this change, but does the factory?
Because, in this case, the buck stops with him
All deadlines are "artificial" and some have a lot of $$$ attached to them (due to regulatory/market/customer/supplier issues)
But I know, a blame culture begets a CYA culture, which begets the opposite of "help me help you"
(hence why such a parameter is hardcoded in the code - the issue here is not stopping the ~~orphan~~ developer crushing machine but why does it exist in the first place)
The worst place I ever worked at had mandatory "ticket refinement" - a feature or a bug couldn't be worked on until it had been through a "refinement session", in which everyone had to chime in, and the ticket wasn't considered refined until everyone on the team fully agreed with the implementation. Naturally over time, this devolved first into writing pseudo-code in Jira tickets and then into near-production code in a google doc overflowing with comments. Leaving that company I told my manager "this is a team of 4 'senior' engineers, I'd suggest you get one proper senior engineer and 3 typists". Nowadays, you could probably shove minutes from those meetings into copilot and call it a day.
Of course, the flipside of this was that comp was about on par with the market, and the perks were top-tier. If you're okay with doing the bare minimum while spending ~20-30 hours a week on total nonsense, it's probably the dream job.
But actually this is a story about the process working.
If the president were told "this is risky, we have to verify that nothing will catch fire if we store it for more than 3 months" (or similar) I'm sure they would have agreed to proceed with caution, but still treat the matter as high priority.
For example, replacing the constant with a file parameter is important, but completely out of scope of the PR, and could lead to unexpected impacts. Sounds like there are enough things to QA with this small change that there’s no need to add other sources of potential bugs.
The naming of the configuration key is also completely ridiculous and a huge waste of time.
Governance is an important aspect of the software development cycle past the PoC stage. Releases shouldn't lead to an existential crisis.
The months of backlog to build against was hard coded? Changing it requires rebuilding and redeploying the entire software stack that runs the factory? This must be some custom in-house MES? The testing requirements to redeploy that must be extensive right? If that is hard coded, who knows what else is. And if the software doesn’t work right, you end up buying or making the wrong parts?
When you try to make every part of a process operate at 100% capacity, you risk creating bottlenecks. There's always some variability in how long tasks take. If every part of your system is running at 100% capacity, then any small disruption or variation can cause a backup. That backup then propagates throughout the system, causing delays everywhere.
When you work in a large organization, any kind of emotional engagement / personal attachment to the work at hand is only going to hurt you.
Also there were 1,280 man-hours of meetings involved here
> Pissed off hours spent on Hacker News: 14.
I hope it was an exaggeration, but also well within the realm of possibility.
This is the only bit that looked like a problem to me:
David: It's for Philip. It we don't do this right away, we'll have to have a layoff.
Judy: OK, then I'll fill out that section myself and put this on the fast track.
2 days later.
If humans understand a change that's in-progress to avoid layoffs, then there's no reason to effect layoffs dogmatically because of a policy which is relying on a laggy process.There's good stuff in here too:
David: Forget the queue. Mark it urgent and send it to Ed immediately.
1 hour later.
Ed (programmer): On line 1252 of Module ORP572, I changed the hard-coded variable MonthsOfBacklog from "3" to "4"...
Shirley (Code Review): It is now against company policy to have any hard-coded variables. You will have to make this a record in the Parameters file. Also, there are 2 old Debug commands, an unassigned variable warning message, and a hard-coded Employee ID that will all have to be fixed before this module can be moved to production.
Ed: I don't have access to Marge.
Julie: Then contact Joe in IT Security. He'll get you permissions.
2 hours later.
Shirley: Your new Parameters record "MonthsOfDemand" needs a better name. The offshore programmers won't understand what this means. Also, it should have an audit trail of changes.
And more bad stuff Ed: What policy is that?
Shirley: It's not exactly written down anywhere. The offshore team is 3 months late updating the wiki, but I assure you, all new Parameter records must satisfy new naming requirements and keep audit trails.
1 day later:
Why would a variable rename take 1 day, perhaps that disgruntled time on HN?This is bad on both the process-side as well as execution. It shouldn't take 2 days to write a test plan as unnecessary as it may seem. Perhaps that's another day spent on HN?
Tony (IT Testing): I see 129281 on Marge, but I have no Test Plan.
Ed: Just run it the old way and the new way and note the increase in the total on the WorkOrdersHours report.
Tony: That's your test plan? No. This affects everything in the factory. I have to have user selected Test Cases, Expected Results, documented Test Runs, and user sign-off.
2 days later:
I've read about bad processes and have even worked in worse environments. This story is nowhere near as bad as it gets. At multiple points problems were solved in <= 2 hours by humans, presumably overriding any silly processes.When I work in an environment without bullshit I love my job and get lots done.
When I work in an environment like this I hate my job and have no motivation to finish two ticket in the time I could finish one, because it would means twice as much bullshit.
This 'one line change' is an existential and fundamental effect on the company, it may very well affect operations otherwise.
'One line of code' can easily blow up a system, and the checks are not there to for the 99% of time time we are 'all good' it's for the 1% of the time when there is sketchiness.
Someone complaining about 'hard coded variables' is perfectly right to do so.
Every single element in this situation is in place for very good reason.
Imagine someone wanting to replace the lock in your Airline door, mid flight - oh, we'll just use a 'regular screwdriver' instead of the one designed for the door, who cares!? It's just an airplane!
The gripes are misplaced: the solution for this situation probably is to have a war room/crunch room situation to move the issue quickly and correctly through the hurdles so it can be done within the timeframe needed.
All of those 'delays in between' were the problem - they did not respect the urgency of the situation.