The old (pre SalesforceDX) best practice was:
- Individual sandboxes for each developer to work in(developer sandbox type)
- QA/Integration/Staging sandbox(es) to integrate/validate everyone's work (partial copy or full copy sandbox type)
- Some form of version control (git, mercurial, subversion, etc...)
Current best practice (Spring/Summer '18) here is:
- Use Salesforce DX
- Some form of version control (git, mercurial, subversion, etc...)
- Do development work in a scratch org
- QA/Integration/Staging sandbox(es) for integration/validation (partial or full copy)
- Some CI/CD (Continuous Integration / Continuous Delivery) tool to automate running tests and deployments
Either way, the general idea behind this is that you want to have something to track history of your code base (Salesforce alone is wholly inadequate here). Version control makes it easier to revert bad changes (if, for example, you use tags in git) and gives you the chance to see if developers are stepping on each others' toes (trying to change the same code, or undo others' changes).
You perform development work in a fairly isolated sandbox. You can have people share sandboxes, but if you're making use of version control, you shouldn't need to (work off of the same branch, pull the latest version, and deploy to your individual sandbox).
After development is finished, you integrate everyone's changes into a single org and run tests to make sure that nothing breaks when combining everyone's components. With pretty much all but the smallest of teams, you'll need the aid of some "diff" tool to help identify what has been changed (to avoid stepping on other developers' toes). Version control can take care of this for you, but if you aren't using version control, there are tools like kdiff, Meld, P4Merge (from Perforce), etc...
Then, the changes are "promoted" to QA/UAT (User Acceptance Testing) so that your users can experience/be trained on the changes.
Finally, your changes are promoted to a staging environment, and then when everything is ready you deploy to production.
Some of the steps here may be consolidated. For a number of years, I was the only one at my company dedicated to working on Salesforce (with my boss doing some occasional development work). Integration and Staging weren't really big concerns with our team of 2, so our flow was Developer sandbox -> QA sandbox -> production.
Using Salesforce DX and version control makes it easy (or at least a lot easier than it used to be) to perform "Continuous Integration", where changes are combined and tests are run on a regular basis. The goal is to not "break the build". A build is "broken" if your code doesn't compile, or if unit tests fail. Doing this regularly (as opposed to all at once, towards the end of a project) helps identify issues earlier (when they are hopefully easier to fix). I don't necessarily think this obsoletes a final integration step, and it generally makes integration a lot easier.