10 ms·
On the evilness of feature branching
- jessaustin 5y agos/\([Ee]vil\)ness/\1/g The noun form of "evil" is "evil".
- chipotle_coyote 5y agoA synonym for the noun "evil" is the noun "evilness", just as a synonym for the noun "good" is the noun "goodness".
- arthurcolle 5y agoThought police are on the way - that's not how you spell double-plus-good
- mumblemumble 5y agohttps://en.wiktionary.org/wiki/evilness#Noun 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 5y ago[deleted]
- deleted 5y ago[deleted]
- jessaustin 5y agoGood 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 when abstract nouns are considered evil, so "evilness" is usually poor diction.
- kazinator 5y agoI'm afraid that this is simply a hypercorrection by analogy to color and such. Indeed, we could not say "the black of feature branches"; it would have to be "blackness". Something that is black (adjective-wise) doesn't "have black" (the noun); it "has blackness". The word "evil" doesn't conform to this restriction; "the evil of feature branches" is fine. Therefore "evilness" is just superfluousnessitude. The word "bad" is color-like. We need "the badness of feature branches", not "the bad of feature branches". But "evil" functions in such a way that it can substitute for "badness", and therefore for "evilness". When we say "the evil of feature branches", the grammar is very similar to "the hypocrisy of using feature branches" or "the iniquity of using feature branches" or "the stink of feature branches" and such. None of these words require an additional suffix; "stink" need not be worked into "stinkiness".
- jessaustin 5y agoYou exhibit a more complete command of English idiom than seen elsewhere in this sub-thread. One suspects that many of the people making these sorts of mechanical arguments haven't actually done much reading in English.
- jcranmer 5y ago"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.
- CRConrad 5y ago> For an analogous example, try replacing "lightness" with "light" in a discussion about color and see how much sense the text makes afterwards. Yeah, that'll get really weird really fast, what with "lightness" being about weight and not colour, and all...
- krypton2k 5y agoIt should probably be "evils"
- tptacek 5y agoIf 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 5y agoMore 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 5y agoAlways 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.
- aidenn0 5y agoI understand it that way as well. Unfortunately if everyone isn't sufficiently disciplined on a team, what happens is that code that takes weeks to develop sits on their machine for weeks. Which is like a feature branch that nobody can see.
- peteretep 5y ago> Therefore I suggested SubVersion This author has much to teach us about evil after all
- gmfawcett 5y agoI think Subversion is fine for a centralized solution. True evil is spelled "C","V","S", but we do not speak its name.
- soperj 5y agoYou speak as someone who has clearly never used PVCS.
- 2OEH8eoCRo0 5y agoClearcase?
- kstrauser 5y agoI think Subversion is the best entry in a category of tools I never want to use again.
- erik_seaberg 5y agoAt least CVS made it obvious that renaming a file wasn’t worth the effort. Subversion pretended to let you and then svnmerge.py took its revenge.
- cactus2093 5y agoThat, 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!
- 5y ago
- bcoughlan 5y agoI 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 5y agoI 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 5y agoI 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 5y agoUnit 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.
- mattwad 5y agoI 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 5y agoThe 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.
- sharken 5y agoPull Requests are great, but i think they can be a serious problem if you have to merge between multiple release branches, with testing and approval for each release branch. Using Trunk-based development with feature flags seems to be me to be the best way of ensuring success with a Pull Request model.
- alkonaut 5y agoTrunk 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 5y agoI 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 That doesn't mean an entire feature has to go in one commit (usually). Often a feature is made up of a series of non-breaking changes that can be layered one at a time, if appropriate.
- sp332 5y agoThat negates one of the major advantages of committing code, which is having a regular backup of your work.
- ehaughee 5y agoMy team makes several commits locally, then rebases, squashes, and pushes the squashed commit to the trunk which has CI. This maintains a local, regular backup of your code and collects features into single commits for the trunk which are easily revertable if found to be problematic. This flow will not work for everyone, but it works very well for us (a team of 8 at a FAANG company). Edit: Rereading your comment, I suspect you mean non-local backups. Our organization has a special remote only visible to you and those you allow for pushing code you'd like to backup off of your box.
- 5y ago
- sam_lowry_ 5y agoAs 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!
- iand 5y agoA question for people practising trunk based development: how do you perform code reviews?
- heelix 5y agoFor us, two places. When the feature is ready to be merged in, it is reviewed by the scrum team. When they say a set of code is ready for production, it gets tagged - and that tag gets the formal peer review.
- tdeck 5y ago> When arriving, I discovered branches were living from 5 days to somewhere 30 days. People had to rebase mainline frequently into their branches, causing lots of rework and spending much non-valuable time on fixing what got broken. This alone doesn't tell me anything about their process. It happens with unbranched workflows as well (unless you use a VCS that prevents more than one person from checking out a file at one time). The fact is, some work takes a few days (or weeks) to get right, and in the meantime other people may have changed those files. This is why `svn update` and `p4 sync` exist.
- deleted 5y ago[deleted]
- kazinator 5y agoWhere is the series? It's just seven numbered headings with no content and nothing to click on.
- kaszanka 5y agoWhat is "PickOS"? Is it https://en.wikipedia.org/wiki/Pick_operating_system https://en.wikipedia.org/wiki/Pick_operating_system?
- hboon 5y agoVersion control and specifically branching strategy (which affects how code is reviewed) has a huge dependency on team size and modularity. Once you go past a certain number of people working on the same module, it’s improbable to have longer living feature branches. You need to have feature flags, if only to make it possible to stay sane (and not necessarily for toggling features exposed to users). So the trick is to figure out where (which side) you are and will be and utilise the right strategy.
- wyaeld 5y agoThe OP is incorrect, most of the large organisations he cites do not practice trunk-based development. Google has a monorepo and what could describe as 'submit patch for code review'. Only certain engineers can approve reviews and trigger the patch being applied to the trunk. https://github.com/google/eng-practices https://github.com/google/eng-practices Many of the others also have variations, but unlikely that any organisation with 1000+ engineers has a monorepo with all of those engineers directly committing to it.
- throwaway83738 5y agoThey never mention the little details in articles like this, like the fact that TBD relies entirely on CI. So what does that mean? - CI requires an automation tool to run a test suite. If you don't have one yet, you need to set one up (and, you know, have a suite of tests to run). hand-waves the idea that the test suite is perfect - If you don't have Pull Requests to gate the test suite before merge to trunk, the tests have to be done pre-merge. But that means it has to run on your laptop, and maybe there's too many tests. So you can do 'fake' Pull Requests, by keeping a CI server with one copy of your repo, and if the tests pass, pushing that copy or change to the 'real' repo. - Even if you do have Pull Requests, or Fake Pull Requests, and a person has to approve them before merge (a good idea), you can still end up with a PR stuck in pending-approval state for eternity. And every time a change hits the trunk, the PR needs to be rebased, retested, and possibly bugs fixed. This means the equivalent of a branch being open for a long time - the whole reason not to use feature branches. - Therefore, assuming you have a test suite, and a CI server, you must only merge very small changes, quickly. Not only must the change be small, you must have review & approval constantly. Or throw out the review/approval step. Or only do it once a day, which goes back towards the long-lived branches that we're trying to avoid. - Of course with all this fast merging, it's increasingly likely you will introduce a bug, because no testing is perfect. So you have to also back out changes quickly. But you still won't always catch them quickly. - With all these changes and reverts happening all the time, the trunk is constantly changing underneath everybody. So you have to rebase or merge constantly. If you don't, it will take you longer to refactor the changes you've just developed to work with the new changes. - And since you can't possibly implement a complex new feature at once with only small commits, you have to use feature flags and other strategies to keep your untested new code from exploding until you think it's ready for prime time. - As all of that is going on, you also of course need to test all this crap. So you'll need a CD system designed to constantly deploy to various environments, potentially managing many constantly changing dependencies and data sets depending on what's being pushed/tested. - That system has at least the same complexity as the CI system, but it's infrastructure-heavy, which means you'll need to lean heavily on DevOps practices and SWE having the tools and training to manage their own deploys/infra. And we haven't even talked about versioning. These are just some of the issues that some books cover (I think) but quaint blog posts about branching never mention. How long will it take your team(s) to implement all of that and completely change their SDLC?
- bartimus 5y agoBut when the version control system is distributed you already have a form of "feature branches" since everyone has a local copy with the changes they're working on. The question is perhaps more about if it's okay to push to trunk or not (without having a review process)?
- sopooneo 5y agoApologies for comment thread hijacking, but I have a related question I hope someone could help me understand. I have worked on many teams that did continuous integration, but never continuous deployment. With continuous deployment, say I branch off trunk and start to implement FeatureA. Just after that, someone else branches off trunk, implements a smaller FeatureB, and merges it back in to trunk. The next day I finish FeatureA and open a pull request back to trunk. All unit tests pass on the code I submitted, and there are no conflicts with trunk. But still, it's not going to be a fast forward merge, so the code I submitted is different than what will be actually be deployed after FeatureA is merged to trunk. And maybe after merge, certain unit tests will fail on trunk. This same truth applies regardless if my pull request is set to squash-merge or rebase. So my question. When do unit tests automatically get run? 1. On my feature branch after the pull request is opened? 2. On trunk after my feature branch is merged? 3. Both 1 and 2? 4. Or am I, as a submitter of code required to continually update my pull requests such that they are always going to be fast forward? That is, if I am waiting on a pull request to be merged, and someone else's PR is merged do I have to rebase my code on top of trunk every time? | |\ |\\ |||FeatureB |// |/ * Passing unit tests in FeatureB do not guarantee passing unit tests here