Thursday, April 17, 2008

Summer '08

Wow! Lots of good stuff coming in the next release - Your Ideas in Summer '08.

These are the ones that I'm looking forward to the most:

  • Filter on Lookup - This should save a lot of people from having to write custom S-Controls to do the filtering.
  • In-line Editing for Views - This should solve a lot of requests for 'Excel-like' editing functionality. (I wonder if this will allow users to edit Related List values as well.)
  • Cross-Object Formula Fields - It will be great to be able to pull some data down from parent objects. (I wonder if this feature will work with Validation Rules as well.)
  • Many to Many Relationships - Custom Report Types solve this problem (see my post here) but it would be really cool if creating Many to Many relationships became even easier to do.
  • Asynchronous Apex - This should add a lot of flexibility, especially in conjunction with making web service callouts from Apex.

Some other solid new features:

Wednesday, April 16, 2008

Update Collision Detection

Have you ever wondered what happens when two people try to modify the same record in

For example, what would happen in this scenario?

1. Sales Rep Bill Smith has a Contact, Jesse Cochran.

2. Sales Rep Bill learns that he needs to update Jesse's last name to Katsopolis.

3. At the same time, another Sales Rep, Roger Jones, learns that he needs to update the company that Jesse works for and that Jesse has a new title.

4. Sales Rep Bill saves his changes.

5. Sales Rep Roger tries to save his changes - and fails.

This is due to a feature called Update Collision Detection that was introduced in the Summer '07 release of salesforce. It's not a super glamorous bit of functionality, but it should let some folks sleep better at night knowing that it's there.

Also, if you're interested in why Jesse changed his last name from Cochran to Katsopolis, you'll want to check out his wikipedia entry:

Sunday, April 13, 2008

Innovator's Dilemma

I drank the Kool-Aid a long time ago - I'm convinced that Software as a service (SaaS) is the next phase in the computing revolution. A lot of established software vendors aren't so sure:

The future is a combination of local software and Internet services interacting with one another. Software makes services better and services make software better. And by bringing together the best of both worlds, we maximize choice, flexibility and capabilities for our customers. We describe this evolutionary path in our industry as Software + Services.


SAP has pioneered the “isolated-tenancy” model that combines the high availability and low risk of a single-tenancy approach with the efficiencies and deployment speed of a multi-tenancy architecture.


Today's CRM deployment options include:
  • On-premises CRM
  • Privately managed on-demand CRM
  • Shared on-demand CRM
  • Hybrid CRM

These companies are trying to convince potential customers that SaaS is a feature, or an option, instead of the way of life that it clearly is. Microsoft, Oracle and SAP are caught in the classic innovator's dilemma - they can see the future clearly, but they can't invest fully in SaaS because doing so would cannibalize their packaged software revenue streams.

History has not been kind to established industry leaders when a disruptive innovation comes along - just ask Kodak.

Wednesday, April 09, 2008 cron

Time-based workflows in salesforce currently execute relative to a time. For example, you can use them to to schedule a task for the case owner to follow up with the customer two days after a
case is closed.

It's not currently possible to schedule time-based workflows to execute at a particular time every day - like a cron job would. For that, we'd need to add some secret sauce to time-based workflows.

The Apex trigger below will populate a custom DateTime field called Midnight_Local_Time__c with, you guessed it, midnight - local time for the running user. In conjunction with a time-based workflow, this trigger would allow you to do things like lock all 'Closed' Case records at midnight
trigger Case_PopulateMidnightLocalTime on Case (after update)
List cases = new List();
for(Case c : [SELECT CreatedDate FROM Case WHERE Id IN AND IsClosed = true AND Midnight_Local_Time__c = null])
CaseTriggerHelper.SetMidnightTime(c, c.CreatedDate);


update cases;

public static void SetMidnightTime(Case c, DateTime dt)
// SFDC defaults 'Midnight' to the 'Time' for this call to newInstance();
DateTime midnightLocalTime = DateTime.newInstance(dt.year(), dt.month(),;
midnightLocalTime = midnightLocalTime.addDays(1).addMinutes(-1);
c.Midnight_Local_Time__c = midnightLocalTime;
If you use this, you'll want to keep in mind that there are limitations around time-based workflows and triggers though:
  • Time-based workflows aren't guaranteed to execute exactly on time, there could be a significant delay in their execution.

  • Unlimited Edition is limited to 20,000 time triggers per org

  • Enterprise Edition is limited to 10,000 time triggers per org
Linvio's CronKit appears to be a useful solution to this problem as well.

Wednesday, April 02, 2008

"No" - In So Many Words

Update January 26, 2014: Jared Spool conveys my thoughts much more clearly in his Beans and Noses post.

Update April 24, 2008: I've been revising this post regularly over the past month. I think that it expresses how I feel about saying "No" to a client, but I reserve the right to modify this post, and my opinion, in the future. Also, I do think that it can be appropriate to tell our clients "No" on occasion, but those scenarios are a topic for another day.

As an IT software engineer, and even as a newbie technology consultant, I didn't realize that my relationships with my clients required a relatively high degree of finesse. I had become accustomed to having very candid conversations with other technical people about what was technologically feasible for a given project. We regularly used the word "No" in these conversations. And we regularly used the word "No" when talking with the business about their requests. Looking back though leads me to believe that telling the business "No" probably hurt my teams' reputation - saying "No" to each other was probably counter-productive in some cases as well.

I've worked with clients whose project goals were to improve customer satisfaction, or to reduce operating expenses, or even to introduce new product lines. At the core, all of these project goals boil down to a desire to improve the business. Our job as technology experts is to provide the business with the tools that they need to accomplish their goals. And just in the way that a carpenter wouldn't like using a hammer that refused to pound nails, our business clients don't like technology experts that refuse to help improve the business by saying "No".

I have learned that it can be much more effective to be indirect and to guide the client to the conclusion that they don't really want to implement their request. Some of my favorite ways of doing this are:
  • "How important is this request compared to the others that we've identified?"
  • "Can you tell me more about why you want to do X?"
  • "That's a great idea, we can do that - have you considered how it will impact Y?"
  • "We can do that, but it will probably increase our timeline/cost." (optional: "Are you willing to accept that?")
  • "That makes a lot of sense, we can definitely do that, but we will probably have to cut out another feature." (optional: Which feature can we remove?")
Customers can request crazy, even impossible, things sometimes, but I've found that my relationships are much more productive if I can think of creative ways to get the customer to consider their request in a different light. The customer may not always be right, but that doesn't mean that we have to tell them that they're wrong.