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