How to Run the Sample Ruby on Rails Force.com Canvas App Using Windows

First off, I am a big fan of Jeff Douglas and all that he has done for the Salesforce community. I am constantly getting really useful stuff from his blog. That was why I was so excited to see a post he did this month about getting a sample Ruby on Rails Force.com Canvas App.

I have been playing with Ruby, Node.js, and Heroku for several weeks now, so this seemed like a great thing for me to install and check out. The problem was that I ran into quite a few issues while trying to get the app working (primarily because I am trying to do all this on a Windows machine/command line) and not a Linux or OSX shell (as Jeff was obviously using).

This post is all about the problems I ran into and what you can do to avoid them if you are trying to run this on a Windows machine. So, if you want to install Jeff’s Sample Ruby on Rails app, first follow the great instructions on Jeff’s blog, which have you setup the connected app in your developer org.

For the next section about installing the rails-canvas app, if you are running all this on a Windows machine, you will want to consider the following when completing that section:

  • You will need to already have Ruby running on your machine. But, you will specifically need to be running an older version of it in order to get this particular tutorial to work. I already had the newest version of Ruby (2.0) running on my machine, but I found out that it would not work until I used a particular older version (1.9.3) that is deemed more stable (especially on Windows, and even more specifically on a Windows 64bit machine, as I am using). Specifically, I was not able to start the rails server, without getting an error with the eventmachine. I imagine, you might be able to get around this eventually (even though I tried several things), but I think the easiest way is to just use the more stable version of Ruby.
  • To install Ruby on Windows, go to the RubyInstaller web site and download the Ruby 1.9.3-p545 version specifically. If you already have the latest version of Ruby running on your machine, you will either need to uninstall that version or use a Ruby version manager tool (such as rvm for Linux or Pik for Windows) to specify that you need to be running the older version of Ruby.
  • If you do not already have Git (which is an open source code versioning application) installed on your Windows machine, you will need to install this first in order to get the source code required for this demo. To do that on a Windows machine, you will want to go to the GitHub page to download the installer for the msysGit project. I would also recommend installing GitExtensions for Windows, as it makes it much easier (via a GUI) to clone (aka, copy) GitHub projects to a Windows machine.GitRailsClone
  • Once Git is installed, you will need to use either GitBash (which is installed on your Desktop by default with msysGit) or GitExtensions (as seen in the picture on the right) to clone the sample code that Jeff has provided on GitHub.
  • Once the project is cloned to your local machine, you will need to open a command prompt and change directories to the directory where your project files are located. You will then need to bundle the project (which will install any of the gems this project requires). This is done by issuing the following commands from the command prompt (as seen in the image below).
cd/
cd apps/rails-canvas
bundle

BundleRailsProject

  • You will now need to return to Jeff’s post and follow the instructions to get the Consumer Secret for your connected app. Once you have this secret number, you will need to add it as an environment variable. In Windows, this is done using the Set command from the command window. Jeff’s post refers to the export command, but this is specific to the Linux environment. In Windows, you will just change the command to be “set” instead of “export”, and “YOUR_SECRET” will be the numeric code you retrieve from Salesforce, such as the following:
set CLIENT_SECRET=YOUR-SECRET
  • Now this step is something Jeff’s post does not refer to, but is VERY important if you want to get this tutorial to work. If you were to proceed at this point with Jeff’s instructions, you could start the server, tunnel through port 443 to 3000 and even start your Canvas app, but you would probably get a connection failed error in your browser. The error is caused by the fact that the OpenSSL library that Rails installer uses has no certificate authorities defined by default. Yes, you “could” get around this by changing a line of code in the Gemfile to use http and not https, but that would defeat the whole purpose of this tutorial, since Canvas requires https. So, to fix this, you will need to download a certificate (cacert.pem) and install it on your local machine. Follow the steps in this GitHub Gist post to do that. I imagine Jeff did not mention this because he has been working with this stuff for so long, he probably installed a cert file on his machine two years ago.
  • You will then need to start the Rails server, which you can do from the Windows command prompt. You do this by entering “rails s” or “rails server” from the command prompt.TunnelsUsingCommandprompt
  • Jeff’s post instructs you to use sudo to run the tunnels command, but this is a linux command and will mean nothing to you Windows users. Alternatively, you will need to fire up another instance of the Windows Command Prompt, but do so by right-clicking on the app and selecting, “Run as Administrator”. This essentially does the same thing that the sudo command does. From there just enter “tunnels 443 300” (as I did in the screenshot on the right).
  • From there, you will want to open your browser and go to the https:/localhost/canvas page and click the “Understand the Risks” button that you should be presented with.
  • Finally, you can go back to Salesforce and browse to your Sample Canvas app (either using the Chatter tab) or by going to the Canvas App Previewer (as seen below).

RailsCanvasApp

Now, I realize with all these steps, you might be thinking, “Why the Heck bother?” I hear ya!

But, there is something very powerful in understanding how to do all this. Salesforce and the Force.com platform will only be powerful if you are able to interact with it as seamlessly as possible and Canvas apps offer a GREAT way to do this. I hope you are able to get it working using the steps in this post and you do not waste two days (as I did). đŸ™‚

Good Luck…

 

 

Motivation and Tips for Passing the Force.com Advanced Developer Certification

AdvancedDeveloperCertVideoIf you are currently pursuing or even just thinking about pursuing the Force.com Advanced Developer Certification, I strongly suggest you check out this video. It is a recording of a panel discussion held at the most recent Dreamforce (late 2013), in which 3 people (seen in the image on the left) who have recently passed the Advanced Developer Certification shared their personal stories.

All three of the speakers had very different backgrounds and experiences in which to share. They each explained why they chose to pursue the certification, as well as specifics about how they studied for the exam and prepared for the coding assignment.

I found the third speaker, Barry Hughes, tips to be particularly helpful, which included some of the following:

  • Prepare for the essay exam by keeping notes and commenting your code as you complete the programming assignment.
  • When doing the programming assignment, focus on the functionality and not the visuals or the security
  • Make sure when you do your unit tests, that they include tests for positive, negative, bulk and specific profile scenarios.
  • Schedule the essay exam when you have the development for the programming assignment nearly finished. You do not have to wait until after you submit it.
  • When taking the actual essay exam, DO NOT try to copy and paste answers from one section to another. If you do, the testing software will deliberately erase what you typed and you will have to re-type it all (or madly find a proctor to get it back, as Barry ended up doing).

All of the panelists seemed to agree on the following advice:

  • Practice as much as possible by going through all of the workbooks available to you on DeveloperForce.
  • Take as much time as you can for the programming assignment and start as soon as you receive it. You will only have 4 weeks to complete. It took the panelists an average of 40 – 80 hours to complete the programming assignment and all had to do it in addition to their regular jobs.
  • Focus heavily on creating good test code for your programming assignment.

If you have not already run across this document about the Road to Advanced Developer Certification, I strongly suggest you read it too.

Add Audio/Video Conferencing to Any Visualforce Page with GoInstant

GoInstantlogo-174x174It is very likely you missed the announcement less than two years ago about Salesforce acquiring a Canadian-based company named GoInstant. It is also likely that even if you attended Dreamforce in late 2013, you missed a very informative session titled, “Build Real-time Multi-User Apps with Visualforce, GoInstant and AngularJS“.

From what I can tell, not much fuss has been made so far about the Backend-as-a-Service provider that was founded in 2010 and acquired by Salesforce in 2012. I imagine that is mostly because up until a few weeks ago, there was not much you could do with GoInstant, other than add chatting capabilities (Hello, Salesforce already has Chatter).  But, with the recent integration with WebRTC (or Web Real-Time Communication), we may be seeing a lot more possibilities popping up.

GoInstant recently released a WebRTC-based widget that lets you EASILY add Audio/Video conferencing capabilities to any Visualforce page. No back-end servers required! And, it is completely free for the first 1000 monthly active users!!!

GoInstant handles all the complexities involved with offering this type of functionality. They handle security, data synchronization and storage, and even scalability. The WebRTC widget specifically lets you initiate, pause, and mute a video stream, all with a single click. And no need for the client to download anything (YEAH). It’s kind of like being able to offer the ease and power of Skype within a secure Salesforce connection.

webrtc-plus-goinstantI can see this type of functionality being really useful for customer support situations, but I can also see it being heavily used in the Enterprise for internal communications. Now, even small to medium companies can offer the type of audio/video chatting once only available to the really BIG enterprises. In fact, I imagine, even the big Enterprises will want to consider dumping their expensive and hard to maintain Unified Communications systems for something like this.

One Gotcha to consider is that currently, WebRTC is only supported in the latest versions of Firefox and Chrome (but I expect the list of supported browsers to be growing very soon). Another thing to consider is that there has still been no final decision made about what standard video codec will be used. (but again, I am sure this will be resolved soon enough).

If you want to see how this works right away, check out this demo created by the clever folks at GoInstant. And, if you want to start playing with this type of functionality in your developer org, I would recommend you check out this GREAT post on Developer Force about how to use the widget in a Visualforce page.

Training Review: Force.com Training on Pluralsight.com

Anyone that reads my blog knows that I am big fan (and regular subscriber) of the Pluralsight training videos. I cannot imagine staying up to date as a programmer without them. At this time, there are only a limited number of courses that cover the Force.com platform (8 to be exact), but I expect new titles will be added very soon. logo-v4

I really think that viewing these courses can be beneficial to anyone studying for the basic or advanced developer certification, or just people working with the Salesforce.com platform in general. These courses can also be valuable to developers (of any platform) that want to determine whether learning more about the Force.com platform is beneficial to them.

Pluralsight offers a free trial that allows you to view 10 days and up to 200 minutes of training. That would allow you to view for free at least one, but maybe two of the courses I describe in this post. Below, I will summarize which courses you should view, depending on where you are coming from and what you are trying to achieve.

First of all, if you only have time to watch one of these courses, I would watch this one:

Force.com Platform: The Big Picture by Don Robins – This is a high-level course that would be very useful for someone brand new to the platform. It is short (1 hours and 24 minutes) and would also be of great interest to experienced developers that have not worked with the platform for long. Robins includes a lot of history about Salesforce and does an excellent job of describing the “Perspective Shift” that is necessary for developers that want to be successful on the platform.

If you are studying for the First-Level Salesforce Developer Exam, I recommend viewing the following course:

Force.com For Developers by Richard Seroter – This is the longest course in the series (5 hours and 47 minutes), but it is also the most thorough. It provides a good overview of the entire platform in a very clear and easy to understand way. Seroter covers many topics that are covered on the 401 Dev exams, such as Reports, Workflows and Approval Processes. He also covers topics on the 501 Advanced Developer Exams, so this course would be good for people studying for that exam as well.

If you are studying for the Second-Level Salesforce Advanced Developer Exam, I recommend viewing the following courses:

Force.com Design Patterns – Part 1 by Adam Purkiss – This course is definitely not for beginners or anyone new to the platform. Purkiss talks about advanced topics such as the use of wrapper classes to get around some of the inherent limitations of SOQL. Some of the code walk-throughs were unpolished and appeared to have not been practiced in advance, but the beginning of each section was very good. My favorite section was the one on Trigger Design Patterns.

Force.com Design Patterns – Part 2 by Adam Purkiss – This course has three distinct segments and I can see the first two (Test Design Patterns and VisualForce Architecture) being especially valuable to anyone pursuing the Advanced Developer Certification. I actually enjoyed this course more than the preceding Part 1, because the examples were more general and the author did not have to waste a lot of time describing how the sample application worked. Purkiss includes many best practices that if you follow will ensure that your code stands the test of time. I really enjoyed the section on how to use Knockout.js to do JavaScript Remoting to create an HTML page that saved custom settings directly to Apex.

Introduction to Visualforce by Matt Lacey – This was my least favorite course, mostly because the speaker had a heavy accent that was hard to understand. He also rushed through the content and the general audio quality of the video was bad. However, the course did provide useful content that would be relevant to anyone studying for the Advanced Developer exam.

If you are an Experienced Software Developer that wants to understand more about the Force.com platform, I recommend viewing the following courses:

Force.com for .NET Developers by Dan Appleman – This course does a very good job of describing the Force.com fundamentals in way that makes sense to .NET developers specifically. Appleman is an experienced author who spent many years creating content for the .NET community, but a few years ago he switched (almost primarily) to working with the Force.com platform. Like myself, Appleman does not dismiss the .NET platform and certainly sees it as still viable, but he also can see the alluring reasons to understand the Force.com platform as well.

Force.com and Apex Fundamentals for Developers by Dan Appleman – Unlike the last course that was specifically designed for .NET developers, this course was designed for developers coming from any platform. It is not a course for people new to programming, but attempts to give experienced software developers a head start to writing “GOOD” code on the Force.com platform. Appleman will tell you about best practices and describe real-world scenarios that only come from hard-earned experience. Most importantly, he covers why design patterns used in other languages do not always apply in Force.com. He focuses on the 4 most important concepts (Execution Context, Use of Static Variables, Limits and Bulk Patterns) that you need to know to start working safely and efficiently in Force.com.

Patterns of Cloud Integration by Richard Seroter – This is NOT a course specifically about Force.com and instead focuses on many technologies that can be used to accomplish integration with cloud applications (on any platform, Force.com included). This course would be of great interest to any technical architects that need to understand to complexities involved with integrating cloud-based applications. Seroter is no doubt an expert in this field and he covers a variety of tools and platforms (such as Biz Talk Server, Windows Azure Service Bus, Mule Cloud Hub and custom code using .NET, node.js, Java, etc) used to integrate Ground to Cloud, Cloud to Cloud, or Cloud to Ground scenarios.

Google Charts and ASP.NET

I recently had the opportunity to redesign a very small web application that was used to display residential housing statistics. The previous application was created over 10 years ago and as you can imagine, now leaves a lot to be desired. It was an ASP.NET application that used many post back operations to render charts using a very limited 3rd party charting tool. It performed slowly and lacked a lot of the key functionality the client wished for (namely the ability to display data for multiple subdivisions within the same chart).

My mission was to create a new ASP.NET solution that performed well on all devices (as this is critical for a web applications success), and was easy to use, yet delivered as much information as possible on a single page. After much consideration, I decided to use the Google Charting API to render the charts. Google Chart tools are simple, free and interactive.

I also utilized Bootstrap to create a modern and responsive design and JQuery to enable a fast and asynchronous user interface. Since this post is titled, “Google Charts and ASP.NET”, I will only focus on the code used to render the actual charts. The solution (as seen below) is what I ended up with.

MLSStats

As this is a technical blog, I will now share with you some of the code used to create this solution. The amount of HTML markup used in the ASP.NET page is actually quite small. The code that is used to render the Google Charts is created dynamically in server-side code and is written back to the web page inside of individual div blocks for each data metric.

To use the application, the user selects a subdivision using any one of the four criterias provided (Parish, Area, City, or Zip).  If the user selects a certain value (for example, “East Baton Rouge” as the Parish), then JQuery and an Ajax call is used to populate the subdivision select box with only the subdivisions for that parish. The user can add as many subdivisions as they want and once all the charts are rendered (which takes only a few seconds), they can flip between each data metric by selecting one of the tabs across the top.

When a user clicks the “Add a Subdivision” button, a server-side call is made to a method which collects all the search criteria and then passes this off to a function called renderChart in a class called Chart. The code (which is seen below) will call the renderChart once for each data metric displayed and will return a string that contains the JavaScript code needed to render that particular Google Chart.

var sc = new SearchCriteria();
sc.parish = ddlParish.Value.Trim() == "" ? null : ddlParish.Value;
sc.area = ddlArea.SelectedValue.Trim() == "" ? null : ddlArea.SelectedValue;
sc.city = ddlCity.SelectedValue.Trim() == "" ? null : ddlCity.SelectedValue;
sc.zip = ddlZip.SelectedValue.Trim() == "" ? null : ddlZip.SelectedValue;
sc.sub = Request.Form[ddlSubdivision.UniqueID];
sc.timeFrame = ddlTimeframe.Value;
if (this.optParish.Checked) sc.type = "parish";
if (this.optArea.Checked) sc.type = "area";
if (this.optCity.Checked) sc.type = "city";
if (this.optZip.Checked) sc.type = "zip";

var chart = new Chart();
ltAvgPriceSqFt.Text = chart.renderChart("AvgPriceSqFt", sc);
if (chart.blnDataFound)
{
     ltAvgSalesPrice.Text = chart.renderChart("AvgSalesPrice", sc);
     ltMedSalesPrice.Text = chart.renderChart("MedSalesPrice", sc);
     ltAvgSPLP.Text = chart.renderChart("AvgSPLP", sc);
     ltAvgSPOLP.Text = chart.renderChart("AvgSPOLP", sc);
     ltAvgDOM.Text = chart.renderChart("AvgDOM", sc);
     ltTotalListings.Text = chart.renderChart("TotalListings", sc);
}

Each time a subdivision is added to a chart, it is also added to a Subdivision List stored in the HTTP Cache. Since it is possible for the user to click Add Subdivision more than once, without changing what subdivision is selected, we want to prevent the same subdivision from being added to the cache multiple times. The following code is the first thing executed in the renderChart function:

List lst = new List();
Cache cache = HttpContext.Current.Cache;
if (cache["selectedSubs"] != null)
{
    lst = (List)cache["selectedSubs"];
    if (lst.Count > 0)
    {
        //Make sure the selected subdivision is not the same as one
        //of the ones already cached
        int idx = -1;
        idx = lst.FindIndex(x => x.SubdivisionName == sc.sub && x.Parish == sc.parish
                    && x.City == sc.city && x.Zip == sc.zip);
        if (idx > -1) lst.RemoveAt(idx);
        if (lst.Count > 0) blnMultipleSubs = true;
    } 
}

The next thing to do is to get the data used to render the charts. The renderChart function makes a call out to one of two other functions (either GetSqlDataForMultipleSubs or GetSqlDataForSingleSub) within the Chart class to do this. The code below, which returns a DataTable shows this:

if (blnMultipleSubs)
{
    dt = GetSqlDataForMultipleSubs(numberToReturn, sc, lst);
}
else
{
    dt = GetSqlDataForSingleSub(numberToReturn, sc);
}

The last thing to do is to loop through the data in the DataTable variable named dt and build a string that will be returned by the function. The code below will accomplish this:

if (dt.Rows.Count > 0)
{
    blnDataFound = true;
    str.Append(@"
    google.load(*visualization*, *1*, { packages: [*corechart*] });
    google.setOnLoadCallback(drawChart);
                                
    function drawChart() {
        var data = new google.visualization.DataTable();
        data.addColumn('string', 'Date');");

    if (blnMultipleSubs)
    {
        foreach (Subdivision sub in lst)
        {
            str.Append(" data.addColumn('number', '" + sub.SubdivisionName + "');");
        }
    }

    str.Append(" data.addColumn('number', '" + sc.sub + "');");
    str.Append(" data.addRows([ ");

    for (int i = 0; i <= dt.Rows.Count - 1; i++)
    {
        str.Append("['" + dt.Rows[i]["date"].ToString() + "', ");
        if (blnMultipleSubs)
        {
            foreach (Subdivision sub in lst)
            {
                str.Append(dt.Rows[i][sub.SubdivisionName].ToString() 
               == "" ? "null," : dt.Rows[i][sub.SubdivisionName].ToString() + ",");
            }
            str.Append(dt.Rows[i][sc.sub].ToString() == "" ? "null]" : dt.Rows[i][sc.sub].ToString() + "]");
        }
        else
        {
            str.Append(dt.Rows[i]["number"].ToString() + "]");
        }

        if (i + 1 < dt.Rows.Count)
        {
            str.Append(", ");
        }
        else
        {
            str.Append("]);");
        }
    }

    str.Append(@"
            var options = {width: 850, height: 400, 
           pointSize: 10, chartArea: {left: 80}, curveType: *function*, ");
                    
    if (numberToReturn == "AvgPriceSqFt")
    {
        str.Append(@"vAxis: { format: '$#,###' }, 
        title: *Average Price Per Square Foot for " + sc.timeFrame + "*}; ");
    }
    else if (numberToReturn == "AvgSalesPrice")
    {
        str.Append(@"vAxis: { format: '$#,###'}, 
        title: *Average Sales Price for " + sc.timeFrame + "*}; ");
    }
    else if (numberToReturn == "MedSalesPrice")
    {
        str.Append(@"vAxis: { format: '$#,###' }, 
        title: *Median Sales Price for " + sc.timeFrame + "*}; ");
    }
    else if (numberToReturn == "AvgSPLP")
    {
        str.Append(@"vAxis: { format: '#%' }, 
        title: *Average Sales Price/Listing Price for " + sc.timeFrame + "*}; ");
    }
    else if (numberToReturn == "AvgSPOLP")
    {
        str.Append(@"vAxis: { format: '#%' }, 
        title: *Average Sales Price/Original Listing Price for " + sc.timeFrame + "*}; ");
    }
    else if (numberToReturn == "AvgDOM")
    {
        str.Append(" title: *Average Days On Market for " + sc.timeFrame + "*}; ");
    }
    else if (numberToReturn == "TotalListings")
    {
        str.Append(" title: *Total Listings for " + sc.timeFrame + "*}; ");
    }

    str.Append(@" 
        var chart = new google.visualization.LineChart(
             document.getElementById('" + numberToReturn + @"'));");

    if (numberToReturn == "AvgPriceSqFt" || numberToReturn == "AvgSalesPrice"
        || numberToReturn == "MedSalesPrice")
    {
        str.Append(@"
            var formatter = new google.visualization.NumberFormat(
                {prefix: *$*, negativeColor: *red*, negativeParens: true});
            formatter.format(data, 1);");
    }

    str.Append(@" 
        chart.draw(data, options); }");

    str.Append(@" 
    

NOTE: Hover over dots in chart to see individual data points

"); return str.ToString().Replace('*', '"'); } else { blnDataFound = false; str.Append(@" hidestuff('startInfo');

ATTENTION:
No data was found for the " + sc.sub + " subdivision. Please select another subdivision or a different timeframe.

"); return str.ToString().Replace('*', '"'); }

The end result for a call to renderChart will be a string of JavaScript code that will be written back to the HTML page inside of one of the predefined Literal placeholders. For example, a call to renderChart in which there are no other subdivisions in the cache and the search criteria was Parish = “EBR”, Subdivision was “Broadmoor East” and time frame was “5 years”, would produce the following output for just one of the data metrics (in this case the AvgPriceSqFt):


google.load("visualization", "1", { packages: ["corechart"] });
google.setOnLoadCallback(drawChart);


function drawChart() {
var data = new google.visualization.DataTable();
data.addColumn('string', 'Date'); data.addColumn('number', 'BROADMOOR EAST'); data.addRows([ ['2009', 78.36], ['2010', 68.38], ['2011', 61.25], ['2012', 55.76], ['2013', 71.61]]);
var options = {width: 850, height: 400, pointSize: 10, chartArea: {left: 80}, curveType: "function", vAxis: { format: '$#,###' },
title: "Average Price Per Square Foot for 5 Years"};
var chart = new google.visualization.LineChart(document.getElementById('AvgPriceSqFt'));
var formatter = new google.visualization.NumberFormat(
{prefix: "$", negativeColor: "red", negativeParens: true});
formatter.format(data, 1);
chart.draw(data, options); }

I really enjoyed working with Google Charts and found it to be very lightweight and flexible. I did not find it necessary to use the Google .NET Wrapper to work with it and ASP.NET. In fact, I will do a separate post about this since it will take a while to go into why this is the case and this post is already too long.

Hope this helps someone. I will try to save all the code to files and post links to them in the post later.

Why a .NET Developer Loves Force.com

When I graduated from College 20 years ago, I had no idea how much would change in the world of Software Development. Back then, the college I attended taught students COBOL as the primary language (and yes, I realize that some people reading this will not even know what that is).

It is lucky for me that I love learning new things. My entire career has been one VERY long lesson – one that changes on an almost daily basis. Blink and you’ll miss the next great language, platform or tool.

While learning new things never bothered me, the other day a simple exercise demonstrated to me how much of a hit my productivity has taken as a result of all the constant big changes in the .NET world of development.

I have been focused on .NET development ever since it emerged and before that, I was a big Visual Basic developer. A little over two years ago, I was introduced to the world of Force.com. One of my clients was using Salesforce and they needed to make it work well with the .NET-based Portal platform they were using.

Despite some initial hesitations, I found myself liking the platform more and more. I loved how stable it was and how I did not have to waste days tracking down crazy server configuration issues (like I did so often when deploying .NET applications). So over the past two years, I have spent as much time as possible learning all about it. A few months ago, I earned the Developer certification and I am currently studying for the advanced certification.

I really came to appreciate the platform when the other day I decided to use it to build a prototype application for a new client. The client was unsure about whether to go further with a project to replace their membership management system. In less than two days (10 hours total), I was able to put together a bare-bones membership management system using a free developer edition.

gbrarams

The prototype application (which has been intentionally blurred to hide sensitive data) included tabs for Documents, Reports, Dashboards, Chatter and Ideas, right off the bat. No programming required. Not a single line of code had to be written. All I did was use the declarative features of the platform to build the app and then I used the Apex Data Loader to import a large group of production member data into the new system. This really helped the client to see the potential of the platform.

I could have never put together something like this on the .NET platform so quickly. The reality is that it would have taken weeks to have put together a .NET prototype with the same amount of functionality. Now, do not get me wrong. I Still love .NET and I am not trying to put it down in any way. But, I have to be honest when I acknowledge that being a .NET developer these days can be a tad bit overwhelming. It seems like just when you have some new tool or language figured out, it has become obsolete and no one is using it any more.

I doubt I will ever get to the point where I am focused solely on any one platform (Force.com or .NET). I think the trick to being valuable as a developer is to keep an open mind and have as vast a skill set as possible. There is never one tool for every job in this business.

I would love to hear what you think???

Book Review: Visualforce Development Cookbook

Not a book for beginners, but GREAT for seasoned Apex developers

I recently had the honor of reviewing the recently published, Visualforce Development Cookbook. The code recipes are great and could really go far in demonstrating the potential of the platform. It is obvious that the author, Keir Bowden has implemented many, if not all of these recipes in real-world scenarios. However, I think this is a dangerous book for developers new to the Force.com platform. In fact, I would not recommend it to anyone who has not worked with the platform for at least one year.

While step by step instructions are provided, along with occasional notes about real-world considerations that should be made, the author does not go into detail about these considerations. For example, on page 36, the author advises readers to use a Utility class to handle creating the data, but does not go into how to actually do this.

Also, the author only provides test code for one of the recipes in the first chapter and then never mentions testing again. Anyone that has worked with the platform for a while knows that writing test code can sometimes take longer and be more difficult than writing the actual code. I could see someone new to the platform using this book to create many changes in their development org and get everyone excited about using the stuff and then never be able to get all the required unit test code together in order to deploy.

The sample code that was provided was easy to download and well organized. It was also formatted properly so that you could cut and paste it straight into your development org. Very little sample code is included in the actual book, which I think helps to ensure that the book stays up to date. As long as the publisher and author continue to update the sample code with each new Salesforce release, the code should stay viable as the platform inevitably changes.

I REALLY liked the chapters on JavaScript, Force.com Sites and Mobile Development and cannot wait to try out some of the recipes included for my clients. My favorite part of the whole book was the fact that the author utilized the Google Hosted Libraries Content Delivery Network rather than static resources for the jQuery code. This was a very smart move and helps to ensure that the code stays viable in the future and also makes use of the latest industry standards.

Some of my favorite Javascript recipes included the tooltips (which featured a slick slidedown effect), the collapsible list elements and the scrolling news ticker. This chapter really demonstrated to me the power of Visualforce and how you can use it to make some powerful and dynamic pages that are unique to your brand.

I really appreciated the final chapter on jQuery Mobile. In fact, if you read only one chapter in this book, read this one. As the author explains, the book is about Visualforce and not mobile development, so it focuses on using HTML5 and the jQuery Mobile Framework to provide the interface code. My favorite recipe in this chapter was the one on navigation and transitions. The author includes transition examples that pop, flip, turn, flow and slide the user from one page to the next. Sweet!!! I will warn you that the code did not display well on my iPhone, but I plan on looking into this further and if I find out the reason why, I will do a separate post about this.

I did find a few inevitable errors in the book as I worked through the code recipes, but the errors were minor and I got past most of them easily. I will report the ones I found to the publisher as errata.

In short, this is an invaluable resource for seasoned Force.com developers, but should be approached with caution for newbies. Force.com is a powerful platform. Much more powerful than most people give it credit for. While this book does include recipes that clearly demonstrate that power, I think experience is needed to help the reader apply the knowledge from this book in the best way possible.

Custom Components Not Rendering Properly

After much searching, I have finally figured out what was causing two frustrating issues I have run into several times and thought I would share it with everyone. Both issues involve creating a Custom Component that includes HTML.

If you use an iframe tag to reference an existing Visualforce page and do not include a certain switch in your URL, the component will not be rendered properly and instead of seeing the rendered Visualforce page, you will just see code in the area where your custom component should be (see top left home component of image below)

CustomComponentsShot1

To avoid this issue, you must add a parameter to the url attribute for your iframe tag. For example, the component titled, Case Count By Status was referencing a Visualforce page named CasesSidebar using an iframe tag. Instead of using src attribute that looks like the following:

src="/apex/CasesSidebar"

you will need to include a switch after the page name called isdtp. The src attribute should instead look like the following:

src="/apex/CasesSidebar?isdtp=lt"

A second issue involves how you enter the HTML for your custom component. If you are not careful about how the HTML is entered, your component will end up displaying the actual HTML code and not the rendered result. For example, if you were to add a Custom Component to the Home page by going to Setup | Customize | Home | Home Page Components and clicking New, you will be brought to a page that looks like the following:

CustomComponentsShot2

If you were to start entering HTML code into the editor below and THEN click Show HTML, you will have a problem when the component renders. Instead of displaying the rendered iframe, you will just see the iframe HTML where your component should be.CustomComponentsShot3

You MUST click the Show HTML checkbox BEFORE you type or paste any code into the editor area. I personally think this is a bug and it should not matter when you click the Show HTML checkbox, as long as you do so before clicking Save.

Perhaps Salesforce will fix this at some point in the future, but in the meantime, I wanted to post this and hopefully it will be found by someone encountering the same issue.

Anatomy of a Great System Document and Why you should Bother

As a professional writer, I admit that I probably focus on documentation more than your average software developer. Over the years, I have learned quite a bit about what goes into making a GREAT system document. I have also noted the extreme lack of good quality system documentation at many of my client locations.

Unfortunately, next to initial design and testing, documentation probably comes in last as far as the amount of time allocated to it for development projects. I have met plenty of programmers who think that the only documentation they have to provide is the occasional comment in their code. By the time the project is over, very few people take the time to go back and create a proper system document.

What most novice programmers fail to realize is that good system documentation is not just a benefit for the client or even for other programmers. It is also not just for large or commercially-based projects. A system document should be created for any size software development project, whether that be for a commercial-based project or just a single-man project done in a small IT department.

Why Bother?

If done properly, a system document can serve many purposes – most of them benefiting the person that created the document. I have been creating system documents for all my software projects for the past 20 years and I have benefited in the following ways:

  • A GREAT system document serves as a calling card for you. It demonstrates that you are a quality worker and that you are attentive to detail. It also reminds people about the work you have done long after you have left a place. This is especially important for software consultants. I actually had a former boss recently contact me for a consulting job, all because he ran across a system document I produced 10 years ago.
  • You can refer to some of your best ones when trying to land a new job or consulting gig. Unless you work exclusively with public facing web sites, it is not always easy to provide a direct link to some of your past work.

    If you keep copies of all the system documents you have produced for employers or clients, you can use these as examples of your quality work. I can promise that offering or producing them for an employer WILL set you apart from the rest of the developers.

  • It can save you LOTS of time. I cannot tell you how many times I have gone back to reference system documentation I have wrote for one project when working on another. In many cases, the stuff I read (even just 6 months later) seems entirely brand new to me and is often very helpful in pointing me in the right direction for resolving a problem or coming up with a good idea.

What Should it Contain? SystemDocTemplate

After years of creating system documents, I have learned a thing or two about what works best. For example, simple and straight to the point language is the best. It should NOT read like a White Paper or some graduate student thesis. It should not even resemble professional software documentation.

If you are creating a system document for a project that involves using some other piece of software, do not include information that could be found in the manual for that software. For example, I created a system document for a large integration project that I worked on. The project involved using a software tool called Scribe to create data transformation scripts. Scribe already has extensive documentation that covers how to use that product. There was no need to include any of that. In fact, my document included a section that stated this fact and pointed the reader to where the online Scribe documentation was located.

The system document you create should contain the kind of information that is not obvious. Get to the point and stick to only including things that someone like you, someone who knows the project intimately would know. The exact length of the document will vary depending on the complexity of the project.

Your document should always include a Last Updated area in the header. This should include a date time that is updated automatically when the document is opened and saved.

As far as what sections to include, I suggest some of the following:

  • What is this about?
    This section is required and should be the first section in every system document you produce.  It should contain information about who originated the project and provide some reasoning for why it was done. The system may be multifaceted and involve multiple applications and scripts, so all of these pieces should be referenced in this section.
  • How do I use or access it?
    This should provide a basic overview of how to use or access the system. If the application is web-based, it should contain a link to it. If it is a desktop or console application, it should specify where the installation files are located. It should also include any special logins and passwords that may be needed.It should assume the reader knows nothing about the system and they are just getting started using it. Including screenshots of the application can be very helpful. This should not be as extensive as a complete user document, but it should at least get the reader logged in to the system and familiar with the basic layout.
  • How do I get started supporting or modifying it?
    This should contain information that a software developer would need to know to access the system as quickly as possible. If the system consists of more than one application, then it should contain links or paths to where the code is located for all applications. If working with the software involves installing any other special software, it should include information about that and what is needed.
  • What if it does not work right?
    Hopefully, the person creating this document has kept notes while working with the system and has undoubtedly encountered issues while testing and deploying. These notes will be helpful in building this section, which should be a bulleted listing of what these issues are and what can be done to resolve them. Remember, the reader of this document is someone who will be tasked with supporting the system and they will likely not be familiar with all the problems you faced creating the system.
  • What kind of changes will I need to make to the system?
    Ask yourself what kinds of changes will likely need to be made to the system and use this section to list those areas. For example, what if the system needs to be moved to different servers? What if the person supporting the application needs to change configuration or database settings?

When should it be created and how much time will it take?

Ideally, you should allocate time in every software project for creating system documentation. The amount of time you allocate is proportional to the size of the project and in my experience is usually about 10% of the total project time. So, if a project takes 100 man hours to design, code, test and deploy, 10 hours should be allocated to creating system documentation.

NOTE that this is separate from any user documentation that you may have to create. The time required to produce user documentation should be included in the total project time. The reader of the system document is someone who will be tasked with supporting or modifying the application. They are likely a software developer and you should assume that they are brand new to the organization.

I understand that creating system documentation like this is not something that comes natural to most developers. But, I can promise that the more you do it, the easier it gets. And, I can also promise you that if you take the time to do it right, you will thank yourself for doing it one day.

Clean Code: Writing Code for Humans

I am a proud monthly subscriber of the online training website Pluralsight. I cannot imagine staying up to date in this field without that subscription. Since my blog focuses on Salesforce concepts, I will tell you that Pluralsight offers several brilliant courses that cover Salesforce.

CleanCodeBut, this post is titled “Clean Code: Writing Code for Humans” by Cory House, a brand new course just offered on Pluralsight. The course is described as the following:

“Anyone can write code a computer can understand, but professional developers write code *humans* can understand. Clean code is a reader-focused development style that produces software that’s easy to write, read and maintain.”

If you are new to programming (of ANY language), then this course if for YOU!

Even if you are an experienced programmer (of ANY language), then this course is for YOU TOO!  I have been doing software programming for over 20 years and have regularly espoused many of the concepts covered in this class, and I learned plenty by watching it. We are ALL prone to writing dirty code and this course has great practical advice for how to avoid this.

If your goal is to remain a programmer (more specifically, a productive and respected programmer), then this course is definitely for YOU!!!!!

Even if you do not already have a subscription to Pluralsight, never fear, they offer a free 10-day trial subscription. So, you really have no excuse. Go and see it I tell you.