[HN Gopher] On the Evilness of Feature Branching ___________________________________________________________________ On the Evilness of Feature Branching Author : sam345 Score : 38 points Date : 2021-07-15 21:30 UTC (1 hours ago) (HTM) web link (thinkinglabs.io) (TXT) w3m dump (thinkinglabs.io) | jessaustin wrote: | s/\([Ee]vil\)ness/\1/g | | The noun form of "evil" is "evil". | mumblemumble wrote: | https://en.wiktionary.org/wiki/evilness#Noun | | Can't even complain that it's a neologism and kids these days | with their bad grammar; "yfelnyss" would appear to predate the | Normans. | | Nor is "evil" in the noun sense a great synonym for "evilness" | in the noun sense. "Evilness" denotes the state of being bad, | while "evil" denotes the badness itself. Evilness is the | correct word here. Using "evil" would have been, if we want to | be really pedantic (I hope I can safely assume that we do), | been mildly nonsensical. | [deleted] | [deleted] | jessaustin wrote: | Good point! I can hardly complain of modern abuses of the | language, given what the Saxons did to it. I await the | seemingly inevitable "evilnessness". | | [EDIT:] However, I can't agree that TFA is about "the state" | of feature branching, or really even that feature branching | is an entity that can possess a state. According to TFA, | feature branching is bad. That's an intrinsic property, not | one that feature branching will be able to overcome with | appropriate prayer and reflection. | | This is usually the case, so "evilness" is usually poor | diction. | chipotle_coyote wrote: | A synonym for the noun "evil" is the noun "evilness", just as a | synonym for the noun "good" is the noun "goodness". | arthurcolle wrote: | Thought police are on the way - that's not how you spell | double-plus-good | jcranmer wrote: | "evil" and "evilness" are not interchangeably usable, | especially if you talk about the evil/evilness of X. The evil | of X (or more frequently, evils of X) refers to the evil things | that have been caused by X. This does not speak to whether or | not X itself is evil, except insofar as doing evil is a sign of | evilness. By contrast, the evilness of X is directly referring | to the degree to which X is or is not evil (although were X not | evil, you'd be more likely to talk about the goodness rather | than evilness of X). | | For an analogous example, try replacing "lightness" with | "light" in a discussion about color and see how much sense the | text makes afterwards. | tptacek wrote: | If I understand the argument, he's saying that rather than use | branches to gate what code actually is live in production, you | should use feature flags or some other modularizing system, and | have a discipline on your team where features that take weeks to | develop should be introduced in a series of short-lived (~1 day) | branches that don't break the build because their code is hidden | by a feature flag (or something) until the whole feature is done. | mumblemumble wrote: | More or less. I'm inclined to agree. More than once, I've been | burned when merging a long-lived feature branch, because it | turns out that, during development, the behavior of some other | portion of the system changed in a way that broke the behavior | of what I was working on, without actually causing any compile- | time or run-time errors. | | You can theoretically guard against that with more and more | automated testing, but that's putting a lot of weight on a | thing that's almost always full of things you forgot to test, | or didn't think you needed to test. | | I've had better luck with feature flags. They don't take | anything away from automated tests or static analysis. They | potentially add a little bit more hassle in the form of | maintaining the flags. (Not nearly as much hassle as sorting | out a merge conflict, though.) The other, quite compelling, | thing they add is a much wider expanse of time during which you | can notice, "Huh, that's funny," when you're doing your mid- | development ad-hoc testing. | | You can, of course, get a similar benefit by making a daily | practice of rebasing your feature branch onto the latest | version of the main branch. But my experience has been that | doing that is annoying, and the thing about annoying things | that you have to actively remember to do is that it's | surprisingly easy to just not remember to do them. | echelon wrote: | Always be merging to master (or main). | | Feature flags make functional overlap and branching explicit | and prevent difficult merge conflicts. They're easier for | humans to reason about, and far easier/safer to do percentage | rollouts with. | mattwad wrote: | I advocate for lots of short-lived branches, and use something | like Git's Pull-Request process to do peer-review. He knocks | GitFlow which is something else entirely IMO where you have long- | lived branches that never get deleted. If you're doing trunk- | based development how does code ever get reviewed first? or it | just doesn't? | sparker72678 wrote: | The pull request flow is fantastic, especially if you have a | tool like GitHub's "Ready to Merge" that shows you if the code | can be merged in without conflict. | | This puts the burden of branch maintenance/compatibility on the | branch owner, and allows a clean and clear place for code | review. | alkonaut wrote: | Trunk based can be sort of ok of you can accept a broken trunk | and features can be kept small enough to give meaningful commits. | If features require 10 commits and you have several teams working | in parallel on different features then you'll have an interleaved | history of various stages of completion of each feature. You need | to make each step of each feature shippable if you use CD - so | e.g you can't commit the removal of an old implementation and | later add the new implementation. | | In all, I'd say the pain of feature branches and PRs is _tiny_ | compared to trunk based development, even for teams as small as | two. | | It's not the industry standard without reason. | brundolf wrote: | I make a point never to commit broken code anyway. If a series | of changes have to be together to not break, I put them all in | one commit. And for organization's sake, commits could still be | tagged by ticket | peteretep wrote: | > Therefore I suggested SubVersion | | This author has much to teach us about evil after all | cactus2093 wrote: | That, plus a few sentences later: "Frankly, at the time, I did | not understand much about branching strategies. It all seemed | too complicated to me. I had hard times trying to fit the | workflow in my head." | | I have no idea whose blog I'm reading here, but he doesn't | exactly sound like someone whose opinion on version control and | branching strategies should count for very much. | | Coming next week - a post about why X is the best programming | language, from someone who hasn't bothered to learn any other | programming languages! | gmfawcett wrote: | I think Subversion is fine for a centralized solution. True | evil is spelled "C","V","S", but we do not speak its name. | soperj wrote: | You speak as someone who has clearly never used PVCS. | 2OEH8eoCRo0 wrote: | Clearcase? | kstrauser wrote: | I think Subversion is the best entry in a category of tools I | never want to use again. | bcoughlan wrote: | I genuinely don't get how you can rely primarily on unit tests to | prevent regressions in your code. They are at such a fine | granularity that most significant changes require restructuring | the "units" in a way that invalidates the tests. Then we're left | with these aenemic E2E tests (because fast!) that only tell you | if something basic is broken. | | These CD advocates seem to be saying that you can take human out | of the testing equation and rely solely on automation. I just | don't buy it. | | I haven't seen true continuous delivery in the wild and I'm | starting to think this is just the empty promises of a club of | consultants who peddle their wares to unsuspecting VPs. Tell me | what I'm missing. | dimes wrote: | I rewrote the backend on a team I used to work on. The service | had a ton of unit tests. Given that this was a full rewrite, | those unit test were useless. I spent the first few days | writing a comprehensive suite of integration tests I could run | against the existing service. These tests directly mimicked | client calls, so the same tests should be just as valid for the | rewritten service. Using these tests, I was able to catch 90%+ | of potential issues before cutting over to the new service. | | Personally, I find unit tests to be mostly useless. Every time | I touch code with a unit test, I also need to change the unit | test. Rather than testing, it feels like writing the same code | twice. | mumblemumble wrote: | I find that, in this life, you usually get what you pay for, | and, compared to other options, unit tests' primary virtue is | that they're inexpensive. | megameter wrote: | Unit tests help verify individual components of a system - | which makes them top-of-mind for library code. | | I think the issue with them lies in that most developers | aren't shipping libraries, they're shipping integrated | systems, so there's no component worth testing. (you can | always invent one, but that's just overcomplicating the | code). | | At the same time, it's also genuinely hard to write good, | principled tests of integrated systems, harder than it is | to code up a thing that kinda-works and then manually | debugging it enough to ship. You have to have the system | set up to be tested, and feature complexity actively | resists this - you fight a losing battle against "YOLO | code" that gets the effect at the expense of going around | the test paradigm. | thatswrong0 wrote: | I've arrived at this exact same conclusion for frontend work | as well. I always go for integration tests first, and only | rely on unit tests if hitting some edge case is hard via | integration test. | jniedrauer wrote: | How does this scale though? If you've got integration tests | that include state, now you've got to either run your tests | serially or set up and tear down multiple copies of the state | to prevent tests from clobbering each other. As your project | expands, the tests will take longer and longer to run. Worse, | they'll start to become unreliable due to the number of | operations being performed. So you'll end up with a test | suite that takes potentially multiple hours to run, and may | periodically fail just because. The feedback loop becomes so | slow that it's not helpful during actual coding. At best, | it's a semi-useful release gate. Is there another way? | abystander wrote: | I've seen this more often than not. The pyramid is a | pyramid for a reason, and I'm somewhat skeptical that we | just have to throw out unit tests or they suck or | something. | | You don't have to be a TDD acolyte to find unit tests | useful or essential. | abystander wrote: | > Personally, I find unit tests to be mostly useless. | | Meanwhile I've found myself in the position where people | eschewed unit testing entirely under this "just do | integration tests" thinking and now I'm stuck fumbling around | with flaky and hard to run integration tests that take | forever to run. | | Unit tests are good because they test whether the code you've | written work as you expect. They run instantly. They don't | require a full setup with other integrations. | | This is indispensable - while it's nice to see a service | integrating well and behaving as expected, it's also _very_ | useful to know practically instantaneously that the logic you | 're calling from a controller or something isn't broken. And | if it's really tough you can easily put in breakpoints and | step through, etc. | everyone wrote: | I'm a game dev and over time I've settled on using two groups | of tests for my projects. Both at opposite ends of the | spectrum. | | . | | 1. Unit tests. But I only write them for stuff that needs | them.. Eg. Some complex math functions that translate between | coordinate systems; the point of the unit tests is to confirm | that the functions are doing _exactly_ what I think they are | doing. With mathsy stuff it can be very easy to look at the | output of some function and think, that looks fine, but in | reality its actually slightly off, and not exactly what it | should be. The unit tests are to confirm that its really | doing what I think its doing. | | . | | 2.Acceptance tests by a human. Theres a spreadsheet of | everything you can do in the game and what should happen. Eg. | press this button -> door should open.. As we add features we | add more stuff to this list. At regular intervals and before | any release several humans try every test on various | hardware. This is to catch big / complex bugs and | regressions. Its super tedious but it has to be done imo. | Automating this would be an insane amount of work and also | pointless as we are also testing the hardware, you get weird | problems with certain GPUs, gamepads, weird smartphones etc. | | . | | I find those two types of tests to be essential, the bare | minimum. But also anything in between, like some kind of | automated integration testing is just a shittone of work and | will only be useful for a relatively brief period of | development, changes will quickly render those sort of tests | useless. | tablespoon wrote: | > Personally, I find unit tests to be mostly useless. Every | time I touch code with a unit test, I also need to change the | unit test. Rather than testing, it feels like writing the | same code twice. | | I think they're mostly useless when refactoring, but they're | useful when writing new code and and making relatively small | to medium sized changes. For new code, it's helpful to me at | least to express my intentions in a more concrete form and it | gives me more confidence that I didn't miss something. For | making relatively small changes, they help catch fined-gained | regressions. Even if I meant to make a change, a failing test | forces me to think about handling a particular case correctly | that I might have forgotten. | | The kind of unit test I do hate are the ones that are so | mock-heavy that they're pretty much only testing the | structure of your codebase (did you call all the methods the | right order and nothing more?). I was once on a team where | that was pretty much all they wrote, and they were very | resistant to any level of integration unit testing because (I | think) they read in a opinionated book somewhere that low | level tests were good enough (they weren't). | [deleted] | colordrops wrote: | Maybe I'm missing something but when did continuous delivery | imply no human testing? | | My last two jobs have had what I understand to be continuous | delivery, to great success, but perhaps it was something other | than CD. | ehutch79 wrote: | What's being sold as TDD/CD/ETC has a lot of hyperbole | involved. | sparker72678 wrote: | We deploy to production multiple times per day, with no human | intervention, successfully. | | Our test suite includes some unit and full end to end tests, | and yea sometimes a breaking change slips through, we write a | test to catch it next time, and move on. | | (Though our deploy process involves spinning up new instances | to run our code, and our load balance won't switch over to new | boxes if they return 500s, so fully broken deploys don't | actually get hit by customers.) | | Different projects have different complexities and differing | levels of CD viability, but there are definitely many people | truly doing automated continuous deployment all day every day. | alisonkisk wrote: | what counts as "C" in CD? FANG push changes to each of many | components daily, with feature flags. of course each change | goes through stages: dev, preprod, prod over a few days. | fennecfoxen wrote: | > I genuinely don't get how you can rely primarily on unit | tests to prevent regressions in your code. They are at such a | fine granularity that most significant changes require | restructuring the "units" in a way that invalidates the tests. | | Besides less-anemic E2E tests, this is why type systems exist. | | Define a well-typed interface, code to the interface, test the | units -- and then it's hard to make terrible mistakes wiring | things up. To realize the full benefit does, of course, require | substantially better data structures than string-to-Any hashes, | and it requires some proper old-school software engineering | (i.e. injecting a client as an argument and not just mocking | out the someOtherClient.client() method.) And there is some | overhead, though I'd say that a proper null-checking pass alone | would be worth that much. (Sorry, Java, your types are | terrible.) | sam_lowry_ wrote: | As much as I love tdp, he has been promoting the same topic for | years. Time to change and start talking about... euh... CICD | promotions considered evil! ___________________________________________________________________ (page generated 2021-07-15 23:00 UTC)