This is hard to discuss clearly without the rest of the code being visible (sorry—I know that would be interesting but we just can't). But the general reason why that argument doesn't apply is that maintainability is relative to the goals of a project, and making it "trivial to change the use of tables for presentation into semantic HTML" is not a main goal of this project [1]. Meanwhile the cost would be high: it would take a lot of code to give HN's software the property that its markup could easily be switched between two dissimilar structures. High cost and low benefit adds up to not worth doing for this program. (Of course it could be different for other programs.)
And that's merely the best-case scenario; systems that go for that rarely make it to 100%. What usually happens is they find abstractions that give 90% of the desired flexibility, but break down at the problem's edges and require special-casing and workarounds to sort of hobble their way to the finish line. The complexity of that special-casing means you end up giving back a lot of the maintainability you hoped to win with such a design. It's like grabbing a handful of sand: a lot slips through your fingers.
Since we're not going for full decoupling and flexibility, what should we do? Here we differ from what most developers would consider best practice. We don't adopt half-measures, we try to avoid them. Since we're not trying to fully abstract away the structure of the markup, we just let that structure be naked in the code. For example, since 'hide' needs to remove 3 nodes, it just removes 3 nodes. We do it this way not because we don't know the risks of dependencies, but because we know the risks of abstractions: most cost more than they're worth. Programmers have been so steeped in 'best practices' that they tend to incur those costs without being sufficiently aware of them. Alice does it for her feature, Bob does it for his, neither's top priority is the system as a whole, and the costs build up like mercury in the blood. To be fair, most programmers have little choice, given the project they're on and the culture of the profession. You can see how deeply engrained this culture is by the bulk of the responses in this thread. In my experience, one can't fight it. One can only look for a project with different thinking (which btw is why sctb and I are here).
Our profession has a large blind spot about the downside of adding code. Obvious abstractions that have a best-practicey feel (e.g. assigning names to the nodes that 'hide' has to remove, or putting the nodes into a collection so 'hide' need only remove one thing instead of three) are like that old adage "no one ever got fired for buying IBM". You make a suboptimal choice because it feels like you're supposed to and it feels safer. That dooms software. All those little choices add complexity, complexity compounds rapidly, and soon you are paralyzed with bloat. To avoid this you need heightened, even paranoid awareness of the downside, which unfortunately runs opposite to most software culture. I'm actually not very good at it; others are much better [2]. pg never adds a line of code unless he's forced to. Me, I add 10 lines of code, then feel embarrassed and and remove 7 or 8 of them. But at least I feel embarrassed.
So that little number 3 in 'hide' is not there because we're naive and made a rookie error, waiting to be uncovered by the internet—it's because we considered the code that various options would cost, considered what they'd buy us, and decided that in the context of this system the simpler approach was best. That's what I meant about the code being written for maintainability. If you do that in every case and you're lucky and the moon is in Sagittarius, maybe you evade the rigor mortis of complexity and live to hack another day.
[1] In case that sounds like dissing accessibility, I'm not, but it would take time to explain why and I don't think those reasons are in the critical path of this discussion.
[2] If anyone wants more grizzled advice, mine is to search out a programmer who is better at this than you are and make it a career goal to work with them.
Thanks for an interesting answer. I really appreciate to hear the thinking behind the design of the code. But when it comes down to it, the argument seem to be that this piece of code is not supposed to be maintainable because you don't find it important to be able to easily change the HTML. Which again is totally fine if that is a deliberate decision, but there is a difference between arguing that some code is designed for maintainability and arguing that it it does not need to be maintainable.
As for adding code, note that my suggestion would remove code - removing a single node in code is obviously simpler than removing a fixed number of nodes in a for loop. But you are correct it introduces an abstraction. I appreciate the cost you assign to abstraction, but I personally think this should be weighed against the cost of more complex and fragile code as here.
Again, I'm not criticizing the code itself, just the assertion that the code is super maintainable. The proof of the pudding is in the eating. If it is too costly to accommodate users using screen readers (how few and unimportant they may be) because of the complexity and risk of changing the HTML, then you have a maintainability issue.
It sounds like we mean different things by maintainability. What I mean is ease of keeping the existing system aligned with its current goals. What you're talking about, I would probably call extensibility, and indeed that is not what our code is written for.
In my experience the way to get extensibility is not to try for it, which leads to bloat, but rather to have the smallest system you can. A smaller system is easier to make a major change to than a larger system, and you don't need to anticipate the change in advance.
I'm sure nobody decided that it was an explicit goal of the site to have accessibility issues. It has those issues for historical reasons. Maintainability to me is being able to fix such relatively minor issues without everything coming crashing down. If it is too difficult to fix then the code is not maintainable whether or not the code is super small and compact. (Note I'm not arguing HN should be redesigned to use semantic markup, just using it as an example of reasonable maintenance.)
I would say simplicity is a really important part of maintainability, but that is not the same as smallness. For example, the for-loop mentioned is quite short and compact, no doubt about that. But to me it it not simple, because it is hard to figure out what it does and what happens when you change it. It is tightly coupled to the particulars of the HTML (even including the whitespace) so you have to dive into the HTML to see what nodes is removed and figure out yourself what is the implicit relationship between these three nodes. So is difficult to change without accidentally breaking something.
Making code simpler often leads to it also being shorter, which is good. But making code shorter without making it simpler just leads to unmaintainable cryptic code.
But I acknowledge maintainability also depends a lot on the people who are supposed to do the maintenance. I personal have limited memory, and I would forget what exactly those three nodes represented within hours of writing the code. I use abstraction and simplicity not because of some lofty ideal, but because I simply do not have the mental capacity to keep this amount of accidental complexity in my head. Your mileage may vary.
And that's merely the best-case scenario; systems that go for that rarely make it to 100%. What usually happens is they find abstractions that give 90% of the desired flexibility, but break down at the problem's edges and require special-casing and workarounds to sort of hobble their way to the finish line. The complexity of that special-casing means you end up giving back a lot of the maintainability you hoped to win with such a design. It's like grabbing a handful of sand: a lot slips through your fingers.
Since we're not going for full decoupling and flexibility, what should we do? Here we differ from what most developers would consider best practice. We don't adopt half-measures, we try to avoid them. Since we're not trying to fully abstract away the structure of the markup, we just let that structure be naked in the code. For example, since 'hide' needs to remove 3 nodes, it just removes 3 nodes. We do it this way not because we don't know the risks of dependencies, but because we know the risks of abstractions: most cost more than they're worth. Programmers have been so steeped in 'best practices' that they tend to incur those costs without being sufficiently aware of them. Alice does it for her feature, Bob does it for his, neither's top priority is the system as a whole, and the costs build up like mercury in the blood. To be fair, most programmers have little choice, given the project they're on and the culture of the profession. You can see how deeply engrained this culture is by the bulk of the responses in this thread. In my experience, one can't fight it. One can only look for a project with different thinking (which btw is why sctb and I are here).
Our profession has a large blind spot about the downside of adding code. Obvious abstractions that have a best-practicey feel (e.g. assigning names to the nodes that 'hide' has to remove, or putting the nodes into a collection so 'hide' need only remove one thing instead of three) are like that old adage "no one ever got fired for buying IBM". You make a suboptimal choice because it feels like you're supposed to and it feels safer. That dooms software. All those little choices add complexity, complexity compounds rapidly, and soon you are paralyzed with bloat. To avoid this you need heightened, even paranoid awareness of the downside, which unfortunately runs opposite to most software culture. I'm actually not very good at it; others are much better [2]. pg never adds a line of code unless he's forced to. Me, I add 10 lines of code, then feel embarrassed and and remove 7 or 8 of them. But at least I feel embarrassed.
So that little number 3 in 'hide' is not there because we're naive and made a rookie error, waiting to be uncovered by the internet—it's because we considered the code that various options would cost, considered what they'd buy us, and decided that in the context of this system the simpler approach was best. That's what I meant about the code being written for maintainability. If you do that in every case and you're lucky and the moon is in Sagittarius, maybe you evade the rigor mortis of complexity and live to hack another day.
[1] In case that sounds like dissing accessibility, I'm not, but it would take time to explain why and I don't think those reasons are in the critical path of this discussion.
[2] If anyone wants more grizzled advice, mine is to search out a programmer who is better at this than you are and make it a career goal to work with them.