[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)