Can’t Miss Salesforce Security Webinar Series

vulnerabilities_checklistI know security is probably not your favorite subject. But these days, it seems like everyday there is another major story coming out about how some big company has a major security breach. A lot of companies use Salesforce because it is secure and trust is so important. But as a developer, you have to realize that there are MANY ways you can bypass all the terrific security features Salesforce has put in place.

Developers have lots of flexibility that gives them power, but with power comes responsibility. It is so important you are aware of all the ways you may inadvertently make your app vulnerable to attack. Unfortunately, most of the documentation on this subject is loooooonnnnnggg and how shall I say this….BORING!

Well, for all you visual learners that really love practical examples, your help has arrived. The Salesforce security team has begun a series of Webinars designed to get developers up to speed with some practical, code-based demonstrations that show:

  1. How we as developers can inadvertently bypass security
  2. What you can do to correct the mistake and make your app secure again

So far there are only 2 webinars in the series, but just watching these two will probably teach you more than you get by trying to pour through and interpret all that other boring documentation.

Hope you find these as helpful and enlightening as I did. And thanks to the Security team for taking the time to put the sample app together along with these webinars.

 

 

Understanding and Monitoring Visualforce View State

What is View State?

Since HTTP is a stateless protocol, any web application that needs to maintain state between page requests has to deal with how to handle View State. Visualforce handles it by using a hidden form element. Data in components and controllers are stored in an encrypted and hidden field on your page (see image below) that must be serialized and deserialized every time the Visualforce page is requested. Large view state sizes can quickly cause pages to suffer performance problems. Additionally, the Force.com platform limits your pages to a maximum view state size of 135Kb.

Like this Post? Then you will really like the “Improving Visualforce Performance” course that I designed for lynda.com. It was based on this post specifically and goes into great detail about each one of the tips in this post. Check it out!

ViewStatePNG

When is View State needed?

I have seen many examples of code on the forums and in blog posts that use the form tag, even though it is really not needed. I imagine this can happen when people copy code snippets and then change them to fit their needs. Beginning developers will likely not realize the potential negative impact that can occur by leaving in a form tag that is not necessary.

If your Visualforce page includes an <apex:form> component, then it is using View State and could suffer performance problems.

Form tags are only needed when the Visualforce page collects input from the user and is required when using certain apex components such as inputField, commandButton, and any of the action tags. However, it is not needed when just displaying output to users, which many Visualforce pages do. So, the first thing you should always ask is, “Is the form tag in my Visualforce page really needed?” If you are not sure, remove it and try saving the page. If another component requires the form tag, then you will get a compile error telling you this.

How to monitor View State

If your page does require a form tag, then you should be aware of how much view state your page is consuming. To monitor view state, you must first enable this by going to My Settings | Personal | Advanced User Details and clicking Edit. Select the Development Mode AND Show View State in Development Mode checkboxes and click Save.

To access the Development mode footer, navigate to a Visualforce page in your browser by replacing the last characters of the url with /apex/PageName. For example, if you have created a page named AccountSearch and your Salesforce Instance is na3.salesforce.com, then the URL should look like this:

https://na3.salesforce.com/apex/AccountSearch

When you do this, a Development mode footer will appear at the bottom of the page and if your page has a form tag, then a View State tab will appear (such as in the image below).

Transient1

The initial view state (which means that no search has been executed yet) for this particular page is very low – only 2.64KB, which is far below the 135KB threshold allowed. But, what if this page had several more apex components, or what if I executed a search returned hundreds or thousands of records? Well, that number could go up rather quickly and this is why you need to be aware of what your pages view state is and to test it against large quantities of data.

How can I lower View State?

If you do find yourself in the position where your page is performing poorly due to view state (or even encountering limit errors), then there are a few things you can do to fix this. If you have to use a form tag, then the first thing you can do is examine your View State using the Development mode footer and determine whether any of your variables can be marked as transient.

The Transient keyword can be used to flag a variable so that it does not get saved to view state. Chances are, all the variables in your page do not need to be saved between page requests and so this is the easiest and fastest way to lower your view state.

For example, take a look at the markup code below which is used to render a simple Account Search form:

<apex:page standardController="Account" extensions="AccountSearchController">  
  <apex:form >  
      <apex:pageBlock title="Search Result">  
          <apex:pageBlockButtons location="top">
              <apex:inputText value="{!searchstring}" label="Input"/>    
              <apex:commandButton value="Search Accounts" action="{!search}"/>  
          </apex:pageBlockButtons>   
          <apex:pageblockTable value="{!acc}" var="a">  
              <apex:column headerValue="Name">  
                  <apex:outputlink value="/{!a.id}">{!a.Name}</apex:outputlink>  
              </apex:column>  
              <apex:column headerValue="Account Number" value="{!a.AccountNumber}"/>  
              <apex:column headerValue="Industry" value="{!a.Industry}"/>  
              <apex:column headerValue="Phone" value="{!a.Phone}"/>  
              <apex:column headerValue="Website" value="{!a.Website}"/>  
          </apex:pageBlockTable>     
      </apex:pageBlock>    
  </apex:form>  
</apex:page>

and the controller look like this:

public with sharing class AccountSearchController { 
    // Matching Accounts
    public List<Account> acc {get;set;}  
    
    // Search Text entered by user
    public String searchString {get;set;}  
       
    //Constructor
    public AccountSearchController(ApexPages.StandardController controller) {  
    } 
    
    // Action method to search for Accounts  
    public void search() {  
        String searchWord = searchString + '%';  
        acc= [SELECT AccountNumber,Name,Phone,Industry,Website 
              FROM Account 
              WHERE Name like : searchWord];  
    }  
 }

The AccountSearch form is a simple search page that will accept a search string from the user and look for all accounts where the name matches. The results are returned in a variable named acc and the code, as it is now, will store all the records returned in view state. Since this search involves a wild card at the end, if the user looks for all accounts that start with the letter ‘a’ and the org has a lot of accounts, the results could be huge and the view state could easily become too large.

In this example, there are two variables (or properties) that could potentially be marked as Transient: acc and searchString. You can see then both displayed on the View State tab of the Development mode footer (see image below).

Transient

The searchString property is assigned a value when the user enters a word or phrase and clicks Search Accounts. This value is dynamically bound to a SOQL statement and the results are returned to the acc property. Since the searchString value needs to persist between the Get and Post request, it cannot be marked as Transient. But the acc property, which happens to take up the most amount of view state size in KB, contains data results that are just displayed on the page.

Once the results are returned, there is no need to store all the data in view state. The easiest way to reduce view state is to simply add the keyword Transient, so the code for the property declaration now looks like this:

// Matching Accounts
public Transient List acc {get;set;}  

Once the Transient keyword is added, you can save the page and look again at the View State tab. You should see that the acc variable has disappeared entirely and the overall view state size has decreased.

Interested in Learning More?

If you liked this post, then you might be interested in learning more about how you can improve Visualforce Performance by checking out my online course for lynda.com, “Improving Visualforce Performance“. I have an entire chapter dedicated to View State and other chapters involving the following:

  • Evaluating SOQL for efficiency
  • Using Workbench and the Query Plan tool to evaluate queries
  • Reducing use of action tags through Visualforce remoting
  • Working with the StandardSetController class
  • Using static resources

Improving Visualforce Performance – New Online Course Released

Improving Visualforce Perfomance

I am proud to announce that yesterday my online course for lynda.com, “Improving Visualforce Performance” was released. The course is a little over 2 hours long and it focuses on what you need to know to get the most out of your Visualforce performance. It is not a beginning level course (like the first one I did about Developing for Visualforce).

I based the course on a post I did over a year ago called, the “Top 5 Tips for Improving Visualforce Pages“. That post has been the most popular post on this blog for sometime, so I knew this was a good topic.

The course goes into great detail (with examples) of all the tips I covered in that original post. I spent a lot of time developing the examples and scripts for this course and I have to admit I am pretty proud of it. The 5 tips it covers include:

  1. Reducing or Eliminating View State
  2. Evaluating SOQL for Efficiency
  3. Reducing use of Action Tags
  4. Taking Advantage of the StandardSetController
  5. Incorporating Best Practices with JavaScript, HTML, CSS and Images

If you are interested, lynda.com offers a free 10 day trial that you can access here. And until Monday, August 24th, they are offering 30% off the first billing for monthly and annual subscription plans.

I would love to know what you think of the course and what recommendations you have for future course as I plan to be doing more of them.

Why Every Salesforce Developer should be using Trailhead

I have recently been using Trailhead to help me study for an upcoming exam and I have been incredibly impressed with how good it is. I have already posted about the Trailhead modules that cover new material, such as Lightning, but what I was surprised about was how useful it was for reviewing material that I thought I already knew pretty well.

Trailhead is definitely not exhaustive in it’s coverage, but what I like most about the modules is that they go over just the stuff you really need to know. And most importantly, they go over best practices. There are so many examples of inefficient and just plain bad code out there (even on some of the Salesforce sites I hate to say). The text and challenges in the Trailhead modules were well thought out and it is obvious they put a lot of time into developing them. It still Trailheadsurprises me that something this good is free, but fortunately for us, it is.

If you are preparing for one of the Certified Developer tracks, you really need to check out the Developer Trail. It covers a lot of what goes into the exams and the progressively harder challenges really solidify what you just learned. Unlike tutorials that you can just follow in your sleep, the challenges tell you to do something, but not how to do it. And, if you do not do it exactly right, you do not get the points. You actually have to THINK about what you are doing and this is absolutely the best way to learn.

And if you are a certified developer who has been doing this for several years, there is still stuff for you to learn, even when it comes to best practices. As we all know, this platform is changing constantly and that means that so are best practices.

And honestly, it is just fun seeing yourself rack up the points. I really like the WooHoo I get at the end of the challenge. I am proud to say I have 5 badges and over 12,000 points so far (with more to come). How many will you get?

Best Way to Generate Lots of Fake Test Data for Force.com Orgs

I am currently designing a course for lynda.com about improving Visualforce performance. I decided that it was necessary to load my Developer org with a bunch of fake Account data in order to demonstrate some of the performance improvement techniques I was suggesting. I am NOT talking about unit test data, but actual data (just randomly generated). I have tried to generate things like this in the past and it always turned into a big pain. So I went ahead and did some general queries to see if anyone had already slayed this dragon.

At first I was excited about an article I found on DeveloperForce about Generating and Loading Representative test Data for Salesforce and Force.com Orgs. Perfect, I thought. That is just what I need. Unfortunately, I needed it fast and this article details a painfully long way of generating a Ruby on Rails app and installing all sorts of things that I really did not have the time for. I have worked with RoR a bit and knew this method would take way too long.Fake

I did not want to create my own custom Apex factory or install some expensive app off the AppExchange. So back to searching and then I came upon the website GenerateData.com. I was a bit skeptical about it working, but in less than 15 minutes, I had generated my first data set for 100 Accounts and loaded it into my Dev org. I had hit the fake data jackpot!!!!

Now in all fairness, it did take me a few more tries before I got the data exactly the way I wanted, but this method was definitely fast and effective. I will also tell you that you are limited to only generating datasets of 100 records at a time using the Free version, but if you are willing to pay a very small fee (which I was, since I think it is a GREAT deal for all the time it saved me), then you can save data sets and generate as many records as you need.

And to save you a little time, I am including a screenshot of what my final Account Data Set looked like.

GenerateData

With my paid account, I generated 1000 Account records and imported them using the Data Import Wizard in Setup | Data Management. It took me less than 2 hours to get all the data loaded exactly as I needed it. I consider that HUGE!!!

I hope you find this tool as useful as I did. I sure do appreciate the developer, Ben Keen who wrote it! GREAT job!!!!

Pagination and the StandardSetController – No Custom Controller Required

When I designed the code for my online course for lynda.com called “Developing with Visualforce“, I looked for solutions that were as simple as possible. After all, even I will admit that developers do tend to over complicate things unnecessarily.

One of the areas I was covering was handling multiple records and therefore pagination was introduced. In my research for the course, I uncovered dozens of posts/tutorials by developers using Custom Controllers or Extensions to implement this functionality. For a while I thought this was the only way it could be done. Since the underlying message for my course was to find the simplest solution possible, I am glad I dug a little farther and found a way to provide the necessary pagination without the need for a custom controller.

I discovered this while reading through the very excellent online resource titled, “Visualforce in Practice“. This very practical guide was published in 2013 and it contains many tips for development that were discovered through years of practice. Chapter 4 of this guide covers the Standard List Controller and the corresponding StandardSetController. What it revealed was that despite the fact that even the Salesforce documentation leads you to believe that you need a custom controller extension to change the page size, this is not actually. true. You can in fact do it using just the Standard Controller and referencing PageSize member variable. You can then change the page size by adding a command button with a NULL action to force the controller to update.

For example, the page that I created for the course, displayed multiple opportunities that could be edited by the user (see Figure below). At the bottom of the page, I included buttons to page the user through the results, but I also wanted to include a way for the user to change the default of 20 records per page.

EditOpportunities

This was accomplished by simply adding standard apex controls to the bottom of the page. No custom controller or extension required. All the code needed to produce the page you see above is as follows:

 <apex:page standardController="Opportunity" recordSetVar="opportunities" tabStyle="Opportunity">
    <apex:form >
        <apex:pageBlock title="Edit Opportunities" >
            <apex:pageMessages ></apex:pageMessages>
            <apex:pageBlockButtons >
              <apex:commandButton value="Save" action="{!save}"/>
              <apex:commandButton value="Cancel" action="{!cancel}"/>
            </apex:pageBlockButtons>
            <apex:pageBlockTable value="{!opportunities}" var="opp">
                <apex:column value="{!opp.name}"/>
                  <apex:column headerValue="Stage">
                    <apex:inputField value="{!opp.stageName}"/>
                  </apex:column>
                  <apex:column headerValue="Close Date">
                    <apex:inputField value="{!opp.closeDate}"/>
                  </apex:column>
            </apex:pageBlockTable>
            <apex:panelGrid cellpadding="5" cellspacing="5" columns="5" >
                <apex:commandButton value="|<" action="{!first}"  />
                <apex:commandButton value="<" action="{!previous}" rendered="{!HasPrevious}" />
                <apex:commandButton value=">" action="{!next}" rendered="{!HasNext}" />
                <apex:commandButton value=">|" action="{!last}"  />
                <apex:panelGroup >
                    <apex:outputText value="Records/Page"></apex:outputText>&nbsp;&nbsp;
                    <apex:selectList value="{!PageSize}" size="1">
                        <apex:selectOption itemValue="10" itemLabel="10"></apex:selectOption>
                        <apex:selectOption itemValue="15" itemLabel="15"></apex:selectOption>
                        <apex:selectOption itemValue="20" itemLabel="20"></apex:selectOption>
                    </apex:selectList>&nbsp;&nbsp;
                    <apex:commandButton action="{!NULL}" value="Update Page Size"/>
                </apex:panelGroup>
           </apex:panelGrid>
         </apex:pageBlock>
    </apex:form>
</apex:page>

I very much prefer this solution to the one that requires a custom controller. It is easier to maintain and does not involve creating unit tests to deploy. Hope this helps someone else to not over complicate code they are creating. If you are interested in learning more, check out my online course for lynda.com called, “Developing with Visualforce“.

Developing with Visualforce Course just went Live!!!

The Visualforce course I designed for Lynda.com, Developing with Visualforce just went live. You can access it here and even if you are not a member, you can view 4 videos for free.  DevlopingWithVisuaforce

I am pretty proud of the course. I spent a lot of time trying to think through the best way to teach this stuff to beginners. I hope that I succeeded in some small way. I would love to know what you think, good or bad. I don’t mind getting bad feedback because it helps me to get better.

This is just the beginning too. I plan on doing a whole series of courses. This one was an introductory course, so keep that in mind if you are already very familiar with Visualforce. I stressed using declarative solutions and use of standard controllers whenever possible. I really do believe in the KISS (Keep it Simple Stupid) methodology.

Check out one of the free videos Lynda.com makes available:

http://www.lynda.com/player/embed/197238?fs=3&tr=utm_medium=ldc-partner;utm_source=SSPRC;utm_content=11889;utm_campaign=CD16309;aid=CD16309;bid=11889&w=560&h=315;subID5=197238&ps=paused

Oh, and this is the info on the course:

Course Description:
Start developing custom interfaces for the Force.com platform (including Salesforce) using Visualforce. Sara Morgan walks you through the basics of Visualforce, explores its MVC backbone, issues instructions for downloading a free developer edition of the software, and helps you decide if Visualforce is right for your organization. She then explores how to build pages out of common components; enhance pages with tabs, controllers, and extensions; and use the Developer Console to perform more advanced operations—such as editing multiple records, configuring error handling, and unit testing your code. Along the way, you’ll encounter a series of coding challenges that let you practice and expand your Visualforce coding skills.

Topics Include:
What is Visualforce?
Registering for an account
Building a Visualforce page
Building a tabbed page
Configuring permissions
Using standard list controllers and custom controllers
Exploring unit testing

Duration:
3h 4m

 

Heads Up: Custom Home Page Components Using iFrames may stop working in Summer 15

In preparation for my upcoming Visualforce course on Lynda, I discovered something that I think may have a big impact on some people out there that are using iFrames to embed a Visualforce page in the Sidebar. I have seen this technique used by several people over the years to display data in the sidebar and up until just recently the only way to accomplish this was to create a Home Page Component that referenced a Visualforce page using an iFrame. It was kind of a kludgy thing (sort of a hack really, so I am not surprised to see it go). I even wrote about this in a post back in November.

Well, with the Summer 14 release, there were big changes to how the HTML code is handled for these components. If you go to create a component now, you will not find a “Show HTML” checkbox that used to appear at the top right of the Rich text editor. The only exception to this will be if you created a component prior to Summer 14 that did contain Javascript or an iFrame. These components are still supported and will display the old editor (FOR THE TIME BEING!!!!).

BUT, the release notes clearly state the following:

In Summer ’15 we will start removing unsupported code from HTML Area home page components. As a result, components that contain JavaScript, CSS, iframes, or other unsupported markup might stop working properly. To use JavaScript or other advanced HTML elements in your home page component, we recommend that you use a Visualforce Area component instead.

This means that all those orgs that are using this technique may find their pages not working at all next year. You might want to check out SidebarSummarywhether your org has any Visualforce pages or even S-Controls that are still using iFrames, or JavaScript in the Home page component and make a plan to change them over to using the newly available Visualforce Area as the Component type. It really is cool and makes creating these type of components much easier. It is an improvement, but I wanted to make sure everyone was aware of it.

Top 5 Tips for Improving Visualforce Pages

#1 – Reduce or eliminate view state   top5

View State is not your friend when it comes to page performance, so if you do not need it (as in your page does need to persist data between page requests), then do not use it at all. This is especially true for pages that will run on the Salesforce1 mobile platform!!!

How do you not use it all?

Do not include the <apex:form> tag unless you absolutely have to. This tag should only be used when you are accepting input from the user, so if you are only displaying data to the user, you should not have a form tag.

Like this Post? Then you will really like the “Improving Visualforce Performance” course that I designed for lynda.com. It was based on this post specifically and goes into great detail about each one of the tips in this post. Check it out!

And, even if you are accepting input, it is likely that not all the data on your page needs to be submitted through a POST request. For example, you could have a page that lists some account data, but only allows the user to change one particular field. In cases such as these, you could use the Transient keyword in the Controller class to make all the data fields (and especially collections) that are not being changed read-only. This means they will not be stored in the view state and your page will load faster.

You should also consider using JavaScript Remoting to avoid View State state by invoking the Apex Controller or Extension from JavaScript instead. This puts more load on the front-end and typically results in more code, but for certain pages that demand fast performance (especially those on the Salesforce1 mobile platform), this may be a necessary tradeoff to consider. But, if you do decide to go this route, make sure you use very efficient JavaScript code, so you do not violate Tip #5.

#2 – Evaluate SOQL for Efficiency

There are several ways you can write better SOQL code. For starters, ALWAYS make sure you place SOQL queries outside of loops. This should be done no matter what. It will not only make your page perform better, but will help avoid limit errors and should be standard practice. This also applies to DML.

Beyond that essential tip, you should also consider:

  • Only return fields that you are using on the page
  • Use WHERE clauses as much as possible to restrict the number of records returned
  • Use indexed fields in your WHERE clause as it will make the query optimizer work better. Default indexed fields are Id, Name, Owner, LastModifiedDate, and any foreign key or ExternalID fields.
  • Use the LIMIT keyword when possible
  • Use aggregation functions such as COUNT()
  • Use the WITH SHARING keyword in your controllers since the sharing architecture is used by the Query Optimizer and you will only retrieve the records that the users has access to
  • Additional suggestions (per reader JSON Hammerle) are to:
    • Use native (more selective indices) when possible
    • Hash your composite key (if you have one) into the native name field and use this hash in your WHERE clause This is comparable to a skinny table but you don’t have to work with support – and it can be delivered in a managed package.
    • Order your WHERE clause from most selective to least

#3 – Reduce use of Action tags

This kind of goes with tip #1, but since it is so important, I wanted to make it a separate point. Action tags such as <apex:ActionPoller> and <apex:ActionFunction> seem great on the surface since they are VERY easy to use, but they are memory hogs, so limit your use of them and consider alternatives.

Rather than using the ActionPoller tag, you should consider using the Streaming API. It means more code for you, but it results in no view state (remember tip #1). If you do not like the Streaming API, then consider using traditional polling using a Meta tag with a refresh and a window.location.reload.

Rather than using the ActionFunction, ActionSupport, ActionRegion tags, use Visualforce Remoting which uses no view state. Like I said earlier, it results in more code and complexity for you, but for certain pages this may be necessary. Again though, make sure you incorporate efficient JavaScript. Do NOT just copy and paste the first JavaScript snippet you find by doing a Google search.

#4 – Take Advantage of StandardSetControllers when dealing with lists of data

StandardSetControllers, which are used to create list controllers are your friends and you should use them whenever possible. The StandardSetControllers are optimized to work with large data sets of up to 10,000 records and include pagination features (which you should be using) automatically. There is no need for you to do this yourself.

When you do use them, instantiate them using a list of sObjects instead of from a query locator, as this is a more efficient way.

#5 – Incorporate Best Practices with all JavaScript, CSS and Images

No Visualforce page will perform well if it includes poorly used or inefficient HTML technologies. Make sure you incorporate best practices when including things such as Javascript, CSS and images. Things such as this:

  • Remember less is more and smaller is better.
  • Files should be minified and use Static Resources
  • Avoid using global variables
  • Place Javascript at the bottom of the page when possible and use the <script> tag and not <apex:includeScript>
  • Use browser caching when you can
  • Avoid use of iframes

There are tons of documents out there about best practices. Two of my favorites are:

https://developers.google.com/speed/docs/best-practices/rules_intro

http://developer.nokia.com/community/wiki/JavaScript_Performance_Best_Practices

 

 

 

Considerations when using Javascript in Visualforce

As part of my research for the new Lynda.com course I am doing on Visualforce, I have been going through posts on the Salesforce forums. I ran across this one in which the poster was asking what was the best way to select multiple checkboxes on a Visualforce page when a “Check All” checkbox was selected.

The best answer that was chosen was a recommendation by someone to use the ActionSupport component. The accepted responder even provided sample code. While the response was technically correct, I did not think it was the best solution. The reason I say this is because if you execute the sample code provided, you will note that there is a significant delay between the time you select the “Check All” checkbox and the time the other checkboxes are selected.

What causes the delay?

The ActionSupport component, which adds AJAX support to another component, allows that component to be refreshed asynchronously. While you might first think, “Asynchronous, that executes on the client and that is good and fast, right?”, that is not really the case. You see, when you use ActionSupport, or ActionFunction, or any of the action tags, you are essentially invoking server-side logic that is contained in your controller. This means that the AJAX request includes the pages view state and this can affect performance, as it did in the very simple example from this post.

So why use these controls?

Well, they are much easier to use than some of the other alternatives (which you can read more about here) and typically result in less code. But, if you are a good software developer, then you should not just blindly accept the path of least resistance. The other alternatives (namely Visualforce Remoting) will certainly perform better, but then they do require more code to be written. There is always a trade off, you see.

So, what is the best solution for this problem?

Well, I know you are going to be annoyed when I say this, but the answer is, “it depends”.

You could say the best alternative is one that was suggested by another responder on this post. That responders suggestion to use client-side JSJavascript (such as is provided in this post) was not accepted as the solution, but if you execute the code provided it does execute extremely fast. The difference in performance between the two suggestions is day and night (IMHO). But, this requires you to write and maintain the extra Javascript code.

If you are just sold on the whole, “it is better to use the built-in Action components provided by Visualforce because they simplify the code”, then you might want to consider adding an ActionStatus component right below the ActionSupport component. This is used to provide a message to the user telling them when the process starts and ends. That would prevent the user from just sitting there dumfounded for 1 – 3 seconds while the code was executing.

You might also want to consider using some of the other Javascript alternatives suggested in this excellent Developer Relations post on Using Javascript with Force.com.

You see, it really all depends on what you are trying to accomplish and what skills you already have. If you are blessed to have the time to consider other options, then I suggest you do so. There are often many ways to accomplish the same thing and rarely is one way always the best way.