Salesforce.com/Force.com Team Development

Team development in the Salesforce platform can be very frustrating if you don’t have the right process defined. For developers used to “traditional” software development, it can be painful (it was for us), until you figure out the right way to do it.

Here at Soliant Consulting, we have been working on defining the right process for quite some time. It seems we finally have most of the nuances figured out. We may not have all the answers, but we have a process that works for us. It allows us to keep our code under version control and automatically deploy to our Test/UAT environments through our Continuous Integration server.

Core Technologies

Let’s start from the beginning. What are the main elements that you need to do team development in the Salesforce platform? They are the same ones that you need in any other software platform. You need:

  1. A Version Control system (SVN, Git…)
  2. A separate Development Environment for each developer
  3. Unit Testing (Salesforce provides a JUnit-like framework)
  4. A Continuous Integration server (Jenkins/Hudson, Bamboo, etc.)

As you can see, there is nothing new here. The way you use version control is also very similar to the way you would with any other development environment. This would be how you work with it (using SVN terminology).

Working with Version Control

See my Force.com IDE & SVN post for specifics on how to do these things with the Force.com IDE.

  1. You create a repository for your project
  2. One developer presumably will have a project connected to the Sandbox. This developer will commit all the code to the new repository we just created in step 1. We consider thisthe first commit.
  3. After that, every other developer in the project will check out the project from the repository. This will create a local project for each of them. Then each will give Force.com nature to his project and will connect it to his development org (he will enter the Salesforce credentials for that org). When the Force.com IDE asks you if you’d like to Override/Refresh everything from server, select “NO.”
  4. Now that every developer has his own development environment they just need to do as usual and commit code to, and update from, the repository one or more times a day

Keep in mind that (contrary to what you might have read in some of Salesforce’s documentation) you should treat the repo as the stable version of the code.

Repository = Gospel

Developer Org = Scratch Paper

In some of Salesforce’s documentation, they talk about the org as containing the stable version of the code. However, here they refer to production or to a sandbox where all changes from production are being duplicated. We will see later how to address these issues in the context of our development process.

Continuous Integration

Let’s talk now about Continuous Integration. Some developers might not be as familiar with it as they are with Version Control and Unit Testing.

A CI server can do many things, but let’s list the main tasks it will set it up to perform in the environment of our Salesforce Team Development process. On a scheduled basis (or every time a developer commits to the repo, depending on how we set it up) the CI server will:

  1. Pull the code from the version control repository
  2. Deploy to our test/UAT environment (using the Ant Migration Tool)
  3. Notify the team by email if there was any issue deploying or if any of the tests failed

Steps 2 and 3 are sometimes in reverse order in other development environments. First, the unit tests run, then the code deploys, and finally, functional testing takes place. With Salesforce, however, you can only run the tests from inside an org. We have to deploy first and then run our unit tests, followed by functional tests, if we have any.

Contineous Integration Advantages

Using Continuous Integration has many advantages, among others:

  • Developers don’t need to be running the tests themselves every time they change code if they don’t want to. Depending on the size of the team and the extent of the code change, they might still want to do it anyway. However, for small features and/or changes, they can skip it. The CI server will run all of them and let them know if a failure occurs.
  • There is no need to manually deploy to a test/UAT org for other stakeholders (project managers, business analysts, QA…) to see the status of the project. At all times the test/UAT org that we define will have the most up-to-date version of the code
  • There is immediate feedback to the team if there is an issue with the code. Even if a developer committed some changes without updating if those changes cause any conflict, he (and everyone else in the team) would be immediately notified of the issue. This might also make developers be more careful when committing code.

Demo?

If this was a live presentation, this would be the time where demoed our process. 🙂 Since it’s not, let me try to describe it.

Let’s assume that we already have our code under version control and that we have two developers working on the project. Each of them (let’s call them John and Peter) has a separate development environment, and both are using the Force.com IDE. This could be a common set of events:

  1. Peter makes a change to his code in the IDE.
  2. Force.com will automatically deploy this change to Peter’s development environment.
  3. Peter commits the code to the repository.
  4. Jenkins will detect the change in the repo and launch a build. The build will deploy to a separate org (what we’ve been referring to as our Test/UAT org) and will run all the tests there. Assuming there are no errors, no notification will be sent.
  5. John updates his code from Subversion.
  6. As the code updates from the repo, the Force.com IDE will automatically deploy the new changes to John’s development environment

Now everyone is in sync! You can go to the Test/UAT org and verify that Jenkins automatically deployed the changes there. They are now ready for QA.

Salesforce Development Scenarios

So far we’ve been talking about team development in general terms, and looking at the similarities it has with team development in other platforms. However, the Salesforce platform has some very distinct features, and we will now try to dive a little deeper into those.

There are actually two very distinct types of development in the Salesforce platform:

  1. Packages
  2. Unpackaged applications

A. Developing a Salesforce Package

This is the easier of the two scenarios to deal with. When you are developing a package, you are doing so in isolation from any other code. You don’t have to worry your inability to install third-party managed packages in each of the developer’s orgs (like you do for unpackaged applications).

To do team development in this scenario, you need the following:

  1. A version control repository for the project (as previously mentioned)
  2. One Developer Org per developer (they are free). Each of these should connect to the repository (also previously mentioned)
  3. One Partner Developer Org for testing/QA. The difference between this org and the Developer Orgs is that in this case, you can have up to 20 accounts, which will allow you to test with different profiles easily. (The orgs used for development could also be of this type, but there’s no need for it.) This org should also connect to the repo.
  4. One Developer Org for Packaging, also connected to the version control repository. In this org, you will create the package and upload it to the AppExchange.
  5. Up to four orgs of different editions for User Acceptance Testing (UAT). These orgs will NOT connect to the repo. You will install the package from the AppExchange to verify that the installation process also goes smoothly.

B. Developing a Salesforce Unpackaged Application

This scenario can be a bit trickier, as we’ll shortly see. To do team development in this scenario, you need the following:

  1. A version control repository for the project (as before)
  2. One Developer Sandbox per developer (1 free in Professional Edition and 15 free in Unlimited Edition; more available for a fee). Each of these should connect to the repository
  3.  Possibly one Sandbox for internal testing (Developer Sandbox should be ok)
  4. One Sandbox for UAT (ideally a Full-copy Sandbox)

The main challenge here is that the Enterprise Edition (the most popular one) comes with only one Developer Sandbox. You’ll need to purchase additional ones from Salesforce. Only Unlimited Edition comes with multiple Developer Sandboxes.

In this scenario, developers need to work with Developer Sandboxes because of the possibility of having third-party managed packages installed in production. If there were not managed packages in production (not with the characteristics described below) developers could use Developer Edition orgs. We’ll descrive this in more detail in the “Salesforce Unpackaged App Development Gotchas” section. Bear with me. We are almost there.

Salesforce Package Team Development Gotchas

There are a few important things to take into account when you are developing a Salesforce package with the methodology described in this article:

  1. You should NOT create the Package in any of the developer orgs. Creating a package will add the selected prefix to all classes, files, objects, etc., and may complicate things (more info regarding package creation)
  2. To avoid prefix issues so that your code can deploy to multiple Developer Orgs, you should follow these recommendations:
    1. Do not use any prefix in Apex code (Apex code will work fine without the prefix even after the package has been created)
    2. Wrap your calls from JavaScript to Apex in buttons with try-catch blocks. This calls will not “just work” once you have created the package as Apex does, but using a try-catch block is a reasonable way of circumventing the issue
    3. Wrap your calls to web services in your own app with try-catch too. Calls to methods annotated with @webservice from either JavaScript or from an external application need to use the prefix
    4. Use $RemoteAction when you are making calls to Apex from JavaScript in your VisualForce pages. $RemoteAction will automatically resolve namespaces
    5. Try to avoid dynamic SOQL. Since these queries are generated from text strings, the namespaces won’t be automatically added. You could, for example, return Iterable<sObject> instead of Database.QueryLocator from the start method of classes that implement Database.Batchable.  => This was an issue at some point in the global namespace, but it has been fixed

To automate some of these issues, you may want to check out this Github project that adds namespace prefixes to the metadata source-code

Salesforce Unpackaged Application Team Development Gotchas

Why You Need Developer Sandboxes

Let’s talk in more detail about a topic we’ve been avoiding so far. Why do we need to use Developer Sandboxes instead of Developer Edition Orgs for development? After all the latter ones are free. Well, the issue is that you need to be able to deploy code from one org to another. Not only that, you need to be able to pull any new changes from production and deploy them to all of your development orgs. These changes might have dependencies to third-party managed packages.

Don’t get me wrong; we have nothing against managed packages. They provide great functionality at very reasonable prices (sometimes even free). The problem is that it is sometimes impossible to install a managed package in a Development Org. If you have managed packages installed in production and cannot install them in your development orgs, you can never use that org for development.

Keep an Eye on Metadata References

And why wouldn’t you be able to deploy code that you pulled from production into a Developer Org if there are managed packages installed in production? Because most likely (almost certainly) there will be references somewhere in the metadata to those managed packages. For example, a field might have been added in a layout that is actually a field of an object of the managed package. That field will have a prefix that does not exist in the Developer Org where you are trying to deploy your code.

Ok, but why wouldn’t I be able to install those packages in my Developer Orgs? Don’t package creators allow you to install the packages for free in a Developer Org? Unfortunately, sometimes they do, and sometimes they don’t. There is, for example, a very popular managed package you cannot install in developer orgs. You can install another package of the same vendor with no problem. We’ve seen a client install a managed package in production that has now been deprecated. Therefore, the client cannot install it in any other org. However, if you have a Developer Sandbox, all these packages will be automatically pulled from production, with the rest of the code, and installed.

Beware of Referencing Managed Packages

I’m hesitant to bring up this hack, but it might cross some developers minds. You can try commenting out the sections of the code with references to the managed packages, but this most likely ends in disaster. It would mean that developers don’t see the full picture. They would be testing their work in incomplete environments. It would also be very easy to forget, commenting back in all those changes and end up removing functionality from production that you didn’t intend to remove.

So there you have it. If you are developing traditional Salesforce applications better provision a Developer Sandbox for each developer involved in the project. Otherwise, robust team development will most likely not be possible.

Replicating Production Changes

Another very important issue to keep in mind is that you must replicate all changes made in production to all environments. If a change is part of the metadata, you should instruct the Salesforce admin (or whoever makes changes in production) to replicate the change in one specific Developer Sandbox. Once that change it’s in that Sandbox the Sandbox owner can pull it (use the synchronize perspective from the Force.com IDE to review it) and add it to the repo. At that point, it will propagate to all of the developers’ environments. (If you do not contain the change in the metadata, you will need manually replicate it to all development environments.)

Refreshing the Sandbox

The last thing to keep in mind in this section is that you should only refresh a Sandbox from production after you deploy all changes. Never do that in the middle of an iteration, or you might find yourself in a world of pain. Believe me, I know. 🙂

Conclusion

That’s all for now regarding team development in the Salesforce platform. Don’t forget to take a look at the post regarding how to use the Force.com IDE with SVN. It can clarify questions you might have regarding the specifics of how to do some of the things described in this post. Also, I plan to write another post in the next few weeks regarding the Ant Migration Tool and how to use it with Jenkins. You may want to watch out for it. Until next time!

Have questions? Let us know in a comment below, or contact our team directly. You can also check out our other posts on customizing your Salesforce solution.

11 thoughts on “Salesforce.com/Force.com Team Development”

  1. great article….one of the best I have seen that describes the gotcha’s.

    I wonder…I never see anyone describe how to do do branching and merging in this environment….any hints on that?

    Ideally, before pushing my changes to the CI server, I should pull down the latest from the CI server, run my tests and then push to the server

  2. Hi Edwin,

    I haven’t read anything about branching and merging in Saleforce projects either. I think we are all still trying to learn the basics and haven’t got that far. However, I think it should not be too different from branching and merging in other environments, with the added caveat that some Salesforce components are not part of the metadata and need to be migrated between orgs manually.

    Regarding when to run the tests, in most other development environments (Java, .NET, PHP….) the sequence of steps would be as you say, with the tests running before deploying to the QA environment. However, these two steps are reversed when working with Salesforce. With Salesforce you can only run the tests from inside one of their orgs, so you don’t have any other option but to deploy first then run the tests. You will most likely be using Salesforce’s Ant Migration Tool to deploy the changes to the QA org. If so, you just need to include the “runalltests” property in the target, like this:

    <target name="deployCodeToPackaging">

       <sf:deploy username="${sf.username}" password="${sf.password}" serverurl="${sf.serverurl}" deployRoot="src" runAllTests="true"></sf:deploy>  

    </target>

    Regards,

    Carlos

  3. Nice article. We have a similar set up using SVN and Jenkins CI. However, we started running into problems with schedule jobs.

    As we all know, Salesforce does not allow changes to classes referred in a scheduled job. However, Jenkins CI checks out head revision of trunk from SVN and errors out when ANT tries deploying the changes to sandbox. It is a tedious manual process to delete and recreate schedule jobs every time. We ended up deleting all scheduled jobs every time sandbox is refreshed from prod.

    Do you have any workarounds or ideas?

    Thanks
    Raja

  4. Very good article, indeed !

    However, it would be great if you can talk about salesforce components which are not metadata API accessible i.e. components which have to managed manually in the Target orgs. That may affect CI to some extent.
    Now in our enterprise development, we have really agile developments which need includes in-house developers, product vendors providing Managed package builds, ETL feeds. Testing in target org is imminent. Please share your inputs.

  5.  

    Hi Raja,

    You are right, Salesforce does not let you deploy changes to classes that are referenced from a scheduled job. And as far as I can tell scheduled jobs are not yet exposed as metadata. Thus the only option is to do what you are doing, which is to manually delete the scheduled jobs from the org where the CI Server is deploying too.

    Hopefully, as Salesforce continues to expose more elements through the metadata API, they will also expose scheduled jobs and then we will be able to make the automatic removal part of the build process.

    Regards,

    Carlos

  6.  

    Hi Aman,

    There is a long list of items that are not available in the Metadata API, and that therefore need to be manually migrated between orgs. The list changes with every new release of the platform though, so it’s something to always be watching out for.

    For these elements there is no other option but to manually re-apply the changes from one org to the others. I’d suggest having a central document where you keep track of all these components. You can either use something like GoogleDocs, or you can keep a text file as part of the project and thus under version control. Personally, I like the version control option better, and I like to keep track in this same document of which components have been manually deployed when.

    Hope that helps. Regards,

    Carlos

  7. Hi,

    If we have to implement this feature “Continuous Integration and automation” in the current project using 2-3 resources what might be the estimated time to complete this process.

    Please explain and help.

    Regards,

    Ananth.R.

  8. Carlos, Nicely done.

    Raja, One workaround that I do would be to create an object or custom setting to store the job name, scheduable class, and cron expression. Create a helper class with an abort and schedule method. Then just script these calls both before and after the deploy. Let me know if you need the code I could provide, on iPad right now.

    -Tom

  9. Great article
    Clear, practical and to the point
    I have been going trough so much bad sales force documentation lately
    You should write a book

  10. Mitchell McConnell

    Carlos,

    Muchas gracias por este articulo!

    This and its companion article were exactly what I was looking for, and very well done.

    Mitch

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top