To understand when branching should be done, ask yourself why you branch in the first place.
There are three main reasons why you need to branch:
You have multiple versions of your product out there, and an older version has a defect. In this case, you create a branch with the older version, and fix it on the branch. Otherwise, you have to include all of the new code that you've added since the release.
You have a few dozen programmers working on a project at Release 1.0. When the project gets near the release point, you want to stop adding features and fix bugs. However, that leaves most of your programmers with nothing to do but twiddle their thumbs while the two or three programmers responsible for the release work on finalizing the release. There's simply not enough work for everyone. In this case, you branch Release 1.0 and do your release off of the branch. Meanwhile, the rest of your developers can continue working on Release 2.0.\
You normally have all developers working on the release and making small changes. However, there's a major project that's going to refactor the framework of your product. If you have the developers working on that check their code in the trunk with the other developers, you won't be able to compile your build and test the changes. Instead, you branch this special project into its own code line. Thus, the backend restructuring is done on a side branch while the rest of the development team can continue working on the trunk.
In the last case, the team working off the main trunk needs to make sure their code doesn't fall behind what's going on in trunk. They have to keep merging the changes in trunk to their side-branch. Otherwise, the code differences between the side branch and trunk become too great to do an easy merge.
The question is why is Case #3 so much more difficult than the other two cases. The answer is whether the branches are diverging away from each other or converging towards each other. In Case #1 and Case #2, the branches diverge. In Case #2, the Release 1.0 code will be different from the Release 2.0 code, and the Release 1.0 code will be even more different than the Release 3.0 code. In fact, sometime in the future, the code on the Release 1.0 branch will be irrelevant.
Meanwhile, in Case #3, the branches much converge towards each other. That means you have to keep them in sync. That requires effort and oversight. It takes a lot of energy to make sure the branches, which will eventually have to merge wholesale, must remain in sync.
This is why most sites now do branching when necessary and not use the older system of feature or development branches. Doing so adds a lot of complexity. Each branch has to be managed, and each merge must be carefully reviewed.
By the way, it's one of the reasons that distributed version control systems aren't always better than centralized ones. I've seen too many places that have used Git, then had the developers all work on their own little repository and never talking to each other. A week before the release, we'd get clobbered with a dozen patches and then have a race to merge all of the code into a deliverable version.
A centralize repository forces everyone to work on the same set of files. Add in a continuous build process, and you can make sure there are no surprises come the release. If everyone has to work off a centralized repository anyway, a distributed version control system doesn't really add all that much to the mix, and can cause problems if you allow developers to live in their own little caves.