The whole problem could have been avoided if the agnostic had just added a simple comment stating that the code intentionally only handles strings of 3 or 4 digits.
I really doubt that was the point of the essay. I have seen many a times where different programmer rewrite the entire system and it is not for the lack of proper documentation.
They did. The unit tests covered that piece of functionality. The real issue with the story being why didn't any other the other dev's run the unit tests after making the change?
The only thing shitty about it was that it didn't adequately explain the problem it was solving. However, that isn't apparent by looking at the code, the only way we could know that is either by reading/running the tests or asking the original developer. There would be no reason to rewrite until you had a reason.
As far as I see, the behavior of the function is undefined for non-zip strings. There is no 'if digits.size < 3 or digits.size > 5 raise "invalid zip code"' or 'assert(digits.size <= 5 and digits.size >= 3, "invalid zip code")'.
So, as a programmer with at least "a lot" of experience (these things are hard to judge, especially among folks here), I'm trying to extract some learning from this.
I'm not at all sure about my classification. Probably somewhere between Librarian and Purist, perhaps (but these things feel somewhat harder to apply when most of the code is in C).
Should I fight the urge to re-write code that I see as broken, since it's just me wanting to re-shape the code in my image? That's emotionally somewhat difficult (bad code hurts the eyes) but certainly doable, but it also seems a bit counter-productive since I really think there can be some value in sharing experience. It's also, of course (?) hard to really believe that it's all narcissism, to me bad code feels objectively bad. If that even makes sense.
I guess it boils down to "co-operation is hard" for me, right now. :)
I think I'm an agnostic. "if it already works[1] then trying to fix it is a bug in the programmer's brain".
(Note: I am a user of many ancient and venerable old FORTRAN libraries, which I have no intention of rewriting because "there is a better way." Yes the glue code is a pain, but you don't need to write it very often.)
Cooperation may be hard, but it's also essential. When you see code that hurts your eyes, don't just fix it; discuss it. Set some standards together.
Understand why other people write code like that. If everybody is constantly "fixing" everybody else's code, you're never going to get anything done. Understand the differences and find some common ground. That's the only way to move forward.
I immediately thought that the Librarian one was sensible and correct, whereas the others seemed like very strained satire. So I'm guessing that makes me a Librarian.
But maybe a cynical, world-weary Librarian like the discworld one, as touching someone else's crappy code without some larger plan in mind seems destined to cause you heartache, following the standard "person who last touched it is to blame" rule.
The librarian's change wasn't so bad, since it was functionally equivalent to the previous one. It was also more legible than the previous one, although she probably should have left it alone.
The point is, the code wasn't broken. It just wasn't done the "right" way.
I've had to fire people because they could not stop "refactoring" code that wasn't broken. Their commits were half in the code the were supposed to be working on and half scattered, random changes like the changes from the article.
You're not "sharing experience"; you're wasting time, money and energy. You are insulting your co-workers intelligence. You are pissing off your boss.
Worse, your co-workers now have to merge your random edits into their work because they were actually assigned to work on the section of code you "fixed".
There is nothing worse than doing a pull and finding a bunch of small, conflicting and ultimately useless changes on the head, ruining your morning coffee.
I certainly hope I do whatever I do with a bit more finesse than what you imply. So far co-workers do not seem to be offended, and no boss has ever seemed pissed off to me.
From your remark, it sounds as if you consider "refactoring" to be almost a swear word, and something that should never happen. I just can't agree with that, even with code I've written myself I sometimes realize I did it wrong.
I practice commenting on other people's code a lot online, that seems to work pretty well, too. Of course it's even harder to notice if I'm offending people online.
> From your remark, it sounds as if you consider "refactoring" to be almost a swear word, and something that should never happen. I just can't agree with that, even with code I've written myself I sometimes realize I did it wrong.
Ha! Not really, in my career I think I am still "net negative" for lines of code; I once refactored a 100K line medical diagnostic program down to ~10K lines for instance. What is a swear word is people who use "refactoring" as an excuse to start dicking around with stuff that doesn't need to be fixed.
Refactoring certainly has it's place, but needs to have a purpose: new feature set that requires the rework, performance, what have you. Too many developers just pick something that is working and "refactor" it ... then you end up with the same thing you started with, just "better" and with different bugs.
Many if not most developers have the same feeling, that "bad code" is objectively bad. And how nice it would be if code quality could be graded on a scale. But it really can't - one mans "elegant" is another's "over-engineered". And one mans "simple" is another's "crude".
My perception of "beauty" is the simplest code that could possibly work, with the lowest possible levels of abstraction. I like YAGNI and similar principles. That's a pretty vague formulation though, so while most can probably agree on a high level, the devil is in the details. What exactly is "simple code" for example? Short code? Easy to read? Flexible? All of the above (that'd require Carmack or Thorvalds)? It really is all in the eye of the developer.
I think the takeaway of this excellent article is that whatever your style is, do have respect for differing styles. Don't grade developers or code on what you intuitively feel. Don't assume that everybody else is an idiot and finally don't waste time on debating / enforcing the one true way of doing things.
> Update: Reviewing the comments made elsewhere, I see that this post fell into the Fizzbuzz Trap: By quoting a programming problem—no matter how banal and contrived—the article was bound to provoke a huge amount of dicussion around the correct way to solve the problem, while ignoring the point of the post.
For his next blog post, maybe Raganwald should write about the pitfalls of using allegories.
Not calling dunder methods directly doesn't really need to be in PEP8, they're data model methods for overloading protocols, their whole purpose is to be used by some other "top-level" operation if and when necessary (nb: this may or may not apply when implementing or overloading dunder methods, but that's a special case)
With 10+ years of being a professional programmer I think you will automatically get the insight of being agnostic is really the only way of surviving and keep your passion for your work.
Those who fail at this will stop working as a programmer, move out in the woods, build a cabin and live happy as a farmer.
When you're young you will inevitably always have an attraction for styles that ring the most true to you. You have one single hammer you have learnt to use or even worse, have heard really good programmers at Hacker News prefer to use, and therefore you use this hammer for everything.
You are a poser.
Most programmers have been there. Posers can be extremely sharp and useful if they get to do what they're good at, but they are posers nevertheless and at the start of a humbling journey to agnosticism - getting shit done instead of bickering and posing.
My opinion: there isn't one single good way to do programming. Often, you want your interfaces to be referentially transparent (stateless). Usually, it's best for source code to be in the functional style as well-- but not always. Sometimes, mutable state is exactly what you need. But it shouldn't be the default, unless you're working at a very low level.
There are, on the other hand, a lot of bad ways to do programming: FactoryFactory nonsense, software-as-spec systems, waterfall methodology. We've seen them several times in our careers and have a hair-trigger sensitivity to stupidity, because we've seen it cripple or kill projects.
Great programmers tend to be unforgiving in their condemnation of the bad ways of doing things, but hesitant in accepting one programming model-- even a very good one like Lisp-- as being the One True Way of doing things. As soon as you have a One True Way, some very smart people disagree with you-- and that's a good sign that you're at least partially wrong.
In other words, it's good to be passionate about using the right tools for the job. It's a problem when people think the same tool is right for every job.
It seems that in saying that having a One True Way attitude is wrong, you've developed a Not True Way attitude. Waterfall methodology might work just fine in some situations, software-as-spec works on smaller applications moving to a different platform, and I haven't found one, but I'm sure that the FactoryFactory nonsense can work to keep order in extremely large codebases (I work on a large codebase, and haven't found a need for super abstraction, but that's just me).
Calling these unequivocally bad is counter to the argument you're presenting (which I happen to agree with).
software-as-spec is out of vogue now? I may have misunderstood, but I thought software-as-spec is the same thing as test-driven-development, which I could have sworn is still lauded.
Can you explain why you think they are the same? SW as spec is problematic because whatever the sw does is interpreted as being what it is supposed to do. So how do you identify bugs? At least with TDD the tests serve as some kind of documentation.
I'm no fan of either, generally, but I also don't work on "move fast. break things" type projects.
Sure, but these guys each have the benefit of being King of their Kingdom. Most people writing code have neighbors they need to get along with and cannot rule by fiat.
Not only the benefit, but the responsibility. By mandating a certain "way" and ending the discussion, they essentially nip "the narcissism of small differences" in the bud. As the leader, this is one of the useful things only they can do.
You're missing the point. The purpose of this post was to illustrate how silly little differences in coding style cause lots of unnecessary work. The agnostic's version was the best in this illustration because they knew what the requirements were. You can easily adapt the ascetic's, the librarian's, and the purist's version into the "right" code as well.
The point is that we each have our own different style of doing things, and frankly, I'm a bit incensed that you're using this post to hold up your way of doing things as the "one true" way of doing things while calling everyone else a "poser". I think this comment is exactly what the author is trying to say is bad.
Note: This is a created dilemma, with one horn being a strawman (with namecalling of those who chose that horn), and one horn occupied by the chosen "good position". This is a rhetorical device used to force decisions to the chosen "good position".
So agnostic code has a bug since doesn't raise an Exception in the else clause?
Anyway the others changed the algorithm, interpreting what they believed it should do. That's something unavoidable sometimes due to convoluted code and lack of documentation, but not in this situation.
I like all styles except the one of "Purist" in that example. In that example, the Purist code is way too bloated and boilerplate (if it indeed has tons of subclasses just for such a tiny problem), and I dislike boilerplate.
I'm pretty sure they were all caricatures. The ascetic's code uses a Y-Combinator, which (as I learned earlier today on HN!) is overkill even if you program in a functional style (basically FP's answer to OO's AbstractSingletonBeanFactoryStrategy). The librarian's code isn't particularly bad, but if you've never heard of that function, you'll have to look it up. This makes the code a little less readable.
I think the point of the article isn't to compare these different styles, but to deliver a bigger message: Style isn't that important, just write code that works.
> ...FP's answer to OO's AbstractSingletonBeanFactoryStrategy
That does not really belong to OO. You would be unlikely to find an AbstractSingletonBeanFactoryStrategy in a Smalltalk project for example (even one under the control of a Purist.) You would find it in a JavaEE project, but even then it is not part the platform, it has more to do with convention that has built up around the platform (and the type of Purists it attracts.)
I'm always annoyed by forms that make "state" a required field. Yes, my country does have provinces, but they're utterly irrelevant to any kind of address or other info.
I live in Shanghai. China does have provinces, and they show up in your address. Shanghai isn't part of one; it's its own division of equal rank. Amazon requires a "state", though, so I had to have things sent to myself at <street>, Shanghai, Shanghai China.
This is nothing. In Indonesia nearly half of the population do not have a surname. In Algeria many people have "around 19xx" as their birthday, hand written on their passport. So much for mandatory form fields...
I'm far too insecure to force my taste in code on others like that. Though I find the Ascetics code utterly unreadable (is that why I still don't grasp Lisp?), and the Purist's code ridiculously over-designed.
But still, if someone writes code like that and I'm not the one reviewing it, my instinct is to assume there's a good reason for it to look like that. If I'm reviewing it, you can bet I'll want them to explain why they do it like that, and more importantly: explain what's so wrong about the original code that it needed to be changed.
I don't know what your history is with trying to grasp Lisp is, but if you write code like that, It's bad in pretty much any language. Code is to be read by people. Here is a lisp version of the first snippet in the blog post:
The syntax is a bit different from Ruby, but there isn't a single concept here a programmer doesn't know.
My theory about why such cryptic code gets associated with lisp is because too many people were told they can learn something profound about programming by just jerking around with scheme without actually using it. So a lot of people just play around with abstractions without actually trying to build anything. That might be useful as much as any abstract task is useful(does solving sudoku puzzles make you a better programmer?), but not as useful as these people think. IOW it's just code masturbation. Lispers who actually write useful software avoid such code as much as anybody else, they'll be maintaining it after all :)
If you want to treat a number like a string, why not just treat it like a string? When people enter zip codes online they enter 07045, so why not just store that? Even forget about other countries like Canada it seems like the best way...
Agreed - if you're going to validate anything at all, define a new type and don't hide the constraints checking within a secret unit testing lair. I hope I would be agnostic about the code here though, there is no point rewriting poorly conceived stringly typed code - that's a symptom that such efforts would be part of a losing battle
There are lots of way to accidentally lose a leading zero along the way. For a quick and realistic example make a csv file the looks like:
01234,Hello
import it into Excel, edit something and export it as csv again. Unless you pay careful attention to what you're doing, you've just lost your leading zero.
I like hearing the opinions of guys and gals who have been writing code and supporting users for 10+ years. I want their criticisms. They have earned the right to talk crap about certain ideas.
I only get pissy when someone who does not have experience yet presumes that I need their advice or need them to enlighten me about the latest fad programming technique or language. OK, look... Go do it in the real world for 10 years then come back and give me your opinion, until then, shut the hell up.
This post illustrates the folly of valuing form over function. Certainly we should strive to write code that is readable and robust. However, it's important to remember that before all else the code should actually work.
The example used as a demonstration is a bit like an episode of Three's Company. The premise revolves around a simple misunderstanding, and it's a bit hard to believe that the misunderstanding went on for so long. The original code is a prime candidate for documentation, and there were even unit tests. If you accept the misunderstanding at face value though, the lesson works well enough.
It seems to me that the core of the problem is that programmers are both writers and critiques.
Indeed, imagine a world in which authors would publish in a magazine both their own short stories and a review of a short written by another author for the same magazine.
Unlike our authors in this Magazine From Hell we programmers have objective criteria on which we can base our critique of the work of others when we have to, namely a specifications, coding standards, etc.
He left out the Test Driven Obsessive who insisted on writing tests much more devious than the actual input, and the Machine Learner who thought that iterated map/reduce should be able to generate an optimal function based on that input, and probably others.
True Agnostics don't write unit tests. In the real world, agnostic code starts with just four lines that hide a single business rule, but balloon into gigantic 600-line methods that everybody is afraid to touch because weird business rules from the Singapore office are hidden away in strange code constructs in the middle someplace.
But the agnostic developer doesn't even consider refactoring it, because it "just works".
90% of devs are true agnostics, never refactoring, never unit testing, barely above the fizzbuzz level. Raganwald's example isn't an agnostic at all: he's a faithful parishioner, dutifully worshiping at the Church of St. Agile of the Clean Code but wisely avoiding the fanatics and the church politics.
I always find it fun to read through these kinds of stories, particularly when we all know we've been there, are going to be there at some point, or are sitting there right now. For instance, myself and two other co-workers were working on a project several years back that involved passing around an array of values. I was building out a Swing based UI layer and infrastructure to wrap their logic and database access layer. At some point, something broke in the backend and I tracked the issue down to a block of code that was taking an array of values and constraining it to have no duplicates. The problem being that our dataset could easily have and should have duplicates. I fixed the issue with the comment "This imposed set semantics on something that is not a set."
Granted, I could have written the comment a little better, i.e. more context as to why set semantics were an issue. My co-workers later told me they found my change and spent 3 hours or so trying to figure out if I was right or not, eventually concluding I was. Of course, I was just down the hall and neither I or them thought to go ask the other about why things had changed or if it was a valid change in the first place. A little communication could saved a large amount of time ... Ah well, live and learn.
I made this same mistake refactoring a function to not process duplicates that the original dev caught in code review. I argue that assumptions (intentionally re-processing duplicates) should be explicitly communicated through comments, unit tests, or assertions.
In the article, author states that existing unit tests checked that two digit zip codes were invalid. The question remains how a refactor that fails unit tests was pushed to master.
For no matter how good or bad the Agnostic’s code is, why did the Librarian rewrite the Ascetic’s code?
Because rewriting code that looks ugly is one of the ways people use to begin to identify with the codebase and make it easier to understand for themselves. The example in the article is clearly made up to show how stupid it it to change things that "just work". Except in reality those things are usually ugly, large and complicated, and eventually need to be changed anyway. The way to deal with them is make people responsible for their own code, so that they add tests or at least some comments that explain why and how things are the way they are. Simply being fearful of change and blaming the last person who touched the codebase for all its problems is not a viable long-term strategy.
I think you missed the point. It isn't to show how stupid it is to change things that already work. It is to show how often the motivation for trivial changes is just to make your code appear sophisticated and stand out.
The point isn't very clear from the article. Frankly, I've never seen anyone changing working code simply for the sake of showing off their sophistication, so it feels like a straw-man argument. What does happen quite often is what I described above: people changing code to make it more comprehensible for themselves. If that happens a lot to your code, the answer isn't felling butt-hurt (which seems to be the case with the author) and blaming it on "dysfunctional" personalities of other coders. The answer is to write comments, do better job naming stuff, be clearer about things in general.
The point is very clear. For example, changing a library written in a functional style to a hierarchy of classes and interfaces might be totally reasonable to someone who lives and breathes OOP. To them, the first style is not comprehensible and therefore "wrong". But does it actually solve any problem?
> * Because rewriting code that looks ugly is one of the ways people use to begin to identify with the codebase [...]
Surely you must see that if more than one person is working on the same codebase that this approach does not scale. If everyone on a 6 person team is constantly rewriting the code so that they each understand it better, and each of them has a different way of understanding code, well, that's going to be quite the clusterfuck.
132 comments
[ 3.2 ms ] story [ 171 ms ] threadI prefer code to comment in this case. ;)
I'm not at all sure about my classification. Probably somewhere between Librarian and Purist, perhaps (but these things feel somewhat harder to apply when most of the code is in C).
Should I fight the urge to re-write code that I see as broken, since it's just me wanting to re-shape the code in my image? That's emotionally somewhat difficult (bad code hurts the eyes) but certainly doable, but it also seems a bit counter-productive since I really think there can be some value in sharing experience. It's also, of course (?) hard to really believe that it's all narcissism, to me bad code feels objectively bad. If that even makes sense.
I guess it boils down to "co-operation is hard" for me, right now. :)
(Note: I am a user of many ancient and venerable old FORTRAN libraries, which I have no intention of rewriting because "there is a better way." Yes the glue code is a pain, but you don't need to write it very often.)
[1] or passes the tests, if appropriate.
Understand why other people write code like that. If everybody is constantly "fixing" everybody else's code, you're never going to get anything done. Understand the differences and find some common ground. That's the only way to move forward.
This.
But maybe a cynical, world-weary Librarian like the discworld one, as touching someone else's crappy code without some larger plan in mind seems destined to cause you heartache, following the standard "person who last touched it is to blame" rule.
I've had to fire people because they could not stop "refactoring" code that wasn't broken. Their commits were half in the code the were supposed to be working on and half scattered, random changes like the changes from the article.
You're not "sharing experience"; you're wasting time, money and energy. You are insulting your co-workers intelligence. You are pissing off your boss.
Worse, your co-workers now have to merge your random edits into their work because they were actually assigned to work on the section of code you "fixed".
There is nothing worse than doing a pull and finding a bunch of small, conflicting and ultimately useless changes on the head, ruining your morning coffee.
I certainly hope I do whatever I do with a bit more finesse than what you imply. So far co-workers do not seem to be offended, and no boss has ever seemed pissed off to me.
From your remark, it sounds as if you consider "refactoring" to be almost a swear word, and something that should never happen. I just can't agree with that, even with code I've written myself I sometimes realize I did it wrong.
I practice commenting on other people's code a lot online, that seems to work pretty well, too. Of course it's even harder to notice if I'm offending people online.
Ha! Not really, in my career I think I am still "net negative" for lines of code; I once refactored a 100K line medical diagnostic program down to ~10K lines for instance. What is a swear word is people who use "refactoring" as an excuse to start dicking around with stuff that doesn't need to be fixed.
Refactoring certainly has it's place, but needs to have a purpose: new feature set that requires the rework, performance, what have you. Too many developers just pick something that is working and "refactor" it ... then you end up with the same thing you started with, just "better" and with different bugs.
My perception of "beauty" is the simplest code that could possibly work, with the lowest possible levels of abstraction. I like YAGNI and similar principles. That's a pretty vague formulation though, so while most can probably agree on a high level, the devil is in the details. What exactly is "simple code" for example? Short code? Easy to read? Flexible? All of the above (that'd require Carmack or Thorvalds)? It really is all in the eye of the developer.
I think the takeaway of this excellent article is that whatever your style is, do have respect for differing styles. Don't grade developers or code on what you intuitively feel. Don't assume that everybody else is an idiot and finally don't waste time on debating / enforcing the one true way of doing things.
For his next blog post, maybe Raganwald should write about the pitfalls of using allegories.
If there really is a problem it will be fixed. If it is not considered a Problem it will be archived and documented as "NOT a problem".
And if the 'fix' breaks the system you will not be toasted because hey we talked about this and all(including the boss) agreed we should change this.
https://news.ycombinator.com/item?id=188873
why would you call `__str__` explicitly instead of 1. using str() as you're supposed to or 2. just using print?
Although, amusingly, I can't actually find this rule in PEP-8.
Those who fail at this will stop working as a programmer, move out in the woods, build a cabin and live happy as a farmer.
When you're young you will inevitably always have an attraction for styles that ring the most true to you. You have one single hammer you have learnt to use or even worse, have heard really good programmers at Hacker News prefer to use, and therefore you use this hammer for everything.
You are a poser.
Most programmers have been there. Posers can be extremely sharp and useful if they get to do what they're good at, but they are posers nevertheless and at the start of a humbling journey to agnosticism - getting shit done instead of bickering and posing.
There are, on the other hand, a lot of bad ways to do programming: FactoryFactory nonsense, software-as-spec systems, waterfall methodology. We've seen them several times in our careers and have a hair-trigger sensitivity to stupidity, because we've seen it cripple or kill projects.
Great programmers tend to be unforgiving in their condemnation of the bad ways of doing things, but hesitant in accepting one programming model-- even a very good one like Lisp-- as being the One True Way of doing things. As soon as you have a One True Way, some very smart people disagree with you-- and that's a good sign that you're at least partially wrong.
In other words, it's good to be passionate about using the right tools for the job. It's a problem when people think the same tool is right for every job.
Calling these unequivocally bad is counter to the argument you're presenting (which I happen to agree with).
I'm no fan of either, generally, but I also don't work on "move fast. break things" type projects.
I definitely do not work on "move fast break things" projects.
Trying to imitate them does not make you them. It makes you a poser.
The point is that we each have our own different style of doing things, and frankly, I'm a bit incensed that you're using this post to hold up your way of doing things as the "one true" way of doing things while calling everyone else a "poser". I think this comment is exactly what the author is trying to say is bad.
Anyway the others changed the algorithm, interpreting what they believed it should do. That's something unavoidable sometimes due to convoluted code and lack of documentation, but not in this situation.
I think the point of the article isn't to compare these different styles, but to deliver a bigger message: Style isn't that important, just write code that works.
That does not really belong to OO. You would be unlikely to find an AbstractSingletonBeanFactoryStrategy in a Smalltalk project for example (even one under the control of a Purist.) You would find it in a JavaEE project, but even then it is not part the platform, it has more to do with convention that has built up around the platform (and the type of Purists it attracts.)
A few reasons I've seen where assumptions about how zip-codes work lead to not taking money:
Ireland - no zip-codes (outside Dublin) - dont do mandatory fields
UK - numbers and letters - dont assume only numbers in zip-code
Brazil - 9 digit codes - dont assume max of 6 or 8 characters
But still, if someone writes code like that and I'm not the one reviewing it, my instinct is to assume there's a good reason for it to look like that. If I'm reviewing it, you can bet I'll want them to explain why they do it like that, and more importantly: explain what's so wrong about the original code that it needed to be changed.
My theory about why such cryptic code gets associated with lisp is because too many people were told they can learn something profound about programming by just jerking around with scheme without actually using it. So a lot of people just play around with abstractions without actually trying to build anything. That might be useful as much as any abstract task is useful(does solving sudoku puzzles make you a better programmer?), but not as useful as these people think. IOW it's just code masturbation. Lispers who actually write useful software avoid such code as much as anybody else, they'll be maintaining it after all :)
I only get pissy when someone who does not have experience yet presumes that I need their advice or need them to enlighten me about the latest fad programming technique or language. OK, look... Go do it in the real world for 10 years then come back and give me your opinion, until then, shut the hell up.
The example used as a demonstration is a bit like an episode of Three's Company. The premise revolves around a simple misunderstanding, and it's a bit hard to believe that the misunderstanding went on for so long. The original code is a prime candidate for documentation, and there were even unit tests. If you accept the misunderstanding at face value though, the lesson works well enough.
Indeed, imagine a world in which authors would publish in a magazine both their own short stories and a review of a short written by another author for the same magazine.
Unlike our authors in this Magazine From Hell we programmers have objective criteria on which we can base our critique of the work of others when we have to, namely a specifications, coding standards, etc.
But the agnostic developer doesn't even consider refactoring it, because it "just works".
90% of devs are true agnostics, never refactoring, never unit testing, barely above the fizzbuzz level. Raganwald's example isn't an agnostic at all: he's a faithful parishioner, dutifully worshiping at the Church of St. Agile of the Clean Code but wisely avoiding the fanatics and the church politics.
Granted, I could have written the comment a little better, i.e. more context as to why set semantics were an issue. My co-workers later told me they found my change and spent 3 hours or so trying to figure out if I was right or not, eventually concluding I was. Of course, I was just down the hall and neither I or them thought to go ask the other about why things had changed or if it was a valid change in the first place. A little communication could saved a large amount of time ... Ah well, live and learn.
In the article, author states that existing unit tests checked that two digit zip codes were invalid. The question remains how a refactor that fails unit tests was pushed to master.
Because rewriting code that looks ugly is one of the ways people use to begin to identify with the codebase and make it easier to understand for themselves. The example in the article is clearly made up to show how stupid it it to change things that "just work". Except in reality those things are usually ugly, large and complicated, and eventually need to be changed anyway. The way to deal with them is make people responsible for their own code, so that they add tests or at least some comments that explain why and how things are the way they are. Simply being fearful of change and blaming the last person who touched the codebase for all its problems is not a viable long-term strategy.
Surely you must see that if more than one person is working on the same codebase that this approach does not scale. If everyone on a 6 person team is constantly rewriting the code so that they each understand it better, and each of them has a different way of understanding code, well, that's going to be quite the clusterfuck.