One of the disadvantages of Scheduled APEX is that a scheduled class can’t be updated. Force.com creates an instance of the APEX class when it is scheduled, preventing it from being updated. You can’t edit a scheduled class, or update it via a ChangeSet, the Force.com IDE or a package update.

What’s more, Force.com prevents updates to any dependent classes as well. Thus it is quite easy for a scheduled class to “poison” an application – preventing many, if not all of its components, from being updated. As a result, updates to applications that use Scheduled Apex often require any scheduled jobs to be manually aborted before an update can take place.

It turns out, however, that a recent API update allows use of a design pattern that can help you avoid most of these problems.

Here’s how it works.

You still create a class that implements the Schedulable interface, but this class will be a simple wrapper that defines it’s own interface – call it IScheduleTest. This interface is identical to Schedulable. The execute method of the Schedulable global class creates an instance of a second class that implements the new IScheduleTest interface using the new Type class instantiation method. It then calls the execute method on that interface. It looks like this:

global class ScheduleTest Implements Schedulable
{
  public Interface IScheduleTest
  {
    void execute(SchedulableContext sc);
  }

  global void execute(SchedulableContext sc)
  {
    Type targettype = Type.forName('CalledByScheduleTest');
    if(targettype!=null)
    {
      IScheduleTest obj = 
      (IScheduleTest)targettype.NewInstance();
      obj.execute(sc);
    }
  }
}

The second class looks something like this:

public class CalledByScheduleTest 
  implements ScheduleTest.IScheduleTest
{
  public void Execute(SchedulableContext sc)
  {
    System.debug('called in schedule');
  }
}

What does this accomplish?

You still can’t modify the ScheduleTest class once it’s scheduled, but this class is so simple, you may never need to update it. You can update the CalledByScheduleTest class. Using the Type.NewInstance method to create the class dynamically prevents the platform from seeing it as a dependent class.

I’ve been able to successfully update the CalledByScheduleTest class even during a managed package update as long as the scheduled ScheduleTest class remains unchanged. Though this design pattern is not officially documented (to my knowledge), I see no reason why it should not work reliably going forwards.

This design pattern eliminates one of the major impediments to using Scheduled Apex and is worth not only considering for new designs, but as a possible retrofit to existing applications.