<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Jason Sun</title>
    <description>The latest articles on DEV Community by Jason Sun (@jasonomnivo).</description>
    <link>https://dev.to/jasonomnivo</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F519919%2F29cb56c6-d39d-4bbf-a569-617c8859a712.jpeg</url>
      <title>DEV Community: Jason Sun</title>
      <link>https://dev.to/jasonomnivo</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jasonomnivo"/>
    <language>en</language>
    <item>
      <title>Automating Developer Workflows and Deployments on Salesforce and Heroku</title>
      <dc:creator>Jason Sun</dc:creator>
      <pubDate>Thu, 11 Mar 2021 15:49:23 +0000</pubDate>
      <link>https://dev.to/jasonomnivo/automating-developer-workflows-and-deployments-on-salesforce-and-heroku-1co</link>
      <guid>https://dev.to/jasonomnivo/automating-developer-workflows-and-deployments-on-salesforce-and-heroku-1co</guid>
      <description>&lt;h2&gt;
  
  
  (Heroku and Salesforce - From Idea to App, Part 13)
&lt;/h2&gt;

&lt;p&gt;This is the 13th and last article documenting what I’ve learned from a series of&lt;a href="https://trailhead.salesforce.com/live/videos/a2r3k000001n2Ig/modern-app-development-on-salesforce/?ref=hackernoon.com"&gt; 13 Trailhead Live video sessions on Modern App Development on Salesforce and Heroku&lt;/a&gt;.  In these articles, we’re focusing on how to combine Salesforce with&lt;a href="https://www.heroku.com/"&gt; Heroku&lt;/a&gt; to build an “eCars” app—a sales and service application for a fictitious electric car company (“Pulsar”).  eCars allows users to customize and buy cars, service techs to view live diagnostic info from the car, and more. In case you missed my previous articles, you can find the links to them below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/jasonomnivo/modern-app-development-on-salesforce-and-heroku-206j"&gt;Modern App Development on Salesforce and Heroku&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/jasonomnivo/jumping-into-heroku-development-48ep"&gt;Jumping into Heroku Development&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/jasonomnivo/data-modeling-in-salesforce-and-heroku-data-services-569e"&gt;Data Modeling in Salesforce and Heroku Data Services&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/jasonomnivo/building-front-end-app-experiences-with-clicks-not-code-2m6e"&gt;Building Front-End App Experiences with Clicks, Not Code&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/jasonomnivo/custom-app-experiences-with-lightning-web-components-4i39"&gt;Custom App Experiences with Lightning Web Components&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/jasonomnivo/lightning-web-components-events-and-lightning-message-service-21b8"&gt;Lightning Web Components, Events and Lightning Message Service&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/jasonomnivo/automating-business-processes-using-salesforce-flows-and-apex-923"&gt;Automating Business Processes Using Salesforce Flows and APEX&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/jasonomnivo/scale-salesforce-apps-using-microservices-on-heroku-43k7"&gt;Scale Salesforce Apps Using Microservices on Heroku&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/jasonomnivo/more-scaling-salesforce-apps-using-heroku-microservices-3k1f"&gt;More Scaling Salesforce Apps Using Heroku Microservices&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/jasonomnivo/javascript-unit-testing-24k7"&gt;Javascript Unit Testing&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/jasonomnivo/apex-unit-testing-on-salesforce-1968"&gt;APEX Unit Testing on Salesforce&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/jasonomnivo/deploying-salesforce-and-heroku-apps-with-ease-1d0g"&gt;Deploying Salesforce and Heroku Apps with Ease&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I’ve been following this Trailhead Live video series to brush up and stay current on the latest app development trends on these platforms that are key for my career and business.  I’ll be sharing each step for building the app, what I’ve learned, and my thoughts from each session.  These series reviews are both for my own edification as well as for others who might benefit from this content.&lt;/p&gt;

&lt;p&gt;The Trailhead Live sessions and schedule can be found here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://trailhead.salesforce.com/live"&gt;https://trailhead.salesforce.com/live&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Trailhead Live sessions I’m writing about can also be found at the links below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://trailhead.salesforce.com/live/videos/a2r3k000001n2Jj/modern-app-development-on-salesforce"&gt;https://trailhead.salesforce.com/live/videos/a2r3k000001n2Jj/modern-app-development-on-salesforce&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/playlist?list=PLgIMQe2PKPSK7myo5smEv2ZtHbnn7HyHI"&gt;https://www.youtube.com/playlist?list=PLgIMQe2PKPSK7myo5smEv2ZtHbnn7HyHI&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Last Time…
&lt;/h1&gt;

&lt;p&gt;Last time, we went over methods of packaging and deploying applications with npm with Javascript as well as several frameworks for packaged and unpackaged development for Salesforce.&lt;/p&gt;

&lt;p&gt;Now that we’ve built and deployed our eCars app, it makes sense that the capstone session of this series reviews the overall application development lifecycle and also covers some ways to automate these processes to make our lives as developers easier.&lt;/p&gt;

&lt;h1&gt;
  
  
  Application Development Lifecycle
&lt;/h1&gt;

&lt;p&gt;Every application, even when successful, requires maintenance, upgrades, and feature additions in order to stay relevant and keep up with the rapidly changing software application world.  As a result, we need a well-regimented process for releasing with confidence that avoids common pitfalls when tinkering with an application’s code that is already out in the wild as well as when many developers are working on a single codebase.  Collectively, this is referred to as “Application Lifecycle Management” or ALM.  Some examples of things that we want to avoid and problems we want to solve with ALM are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Developers’ changes getting overwritten by other developers’ changes and deployments&lt;/li&gt;
&lt;li&gt;  Not knowing exactly what changes are going into a release&lt;/li&gt;
&lt;li&gt;  Knowing a change was made to the app but not knowing who made it, when, and why&lt;/li&gt;
&lt;li&gt;  Manually managing the release process and deploy code&lt;/li&gt;
&lt;li&gt;  Releasing a change, having it break critical functionality, and the need to roll it back easily&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For Salesforce admins who have used Changesets to push releases from sandboxes to Production, you are all probably intimately familiar with the gaps that that release model creates.  Ever try to quickly roll back a Changeset?  It’s basically not possible…&lt;/p&gt;

&lt;p&gt;This is why the modern application lifecycle management model involves multiple steps and tools that help make this process more effective.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Q_ymbMiF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/woq313rsk7q2puubxxy6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Q_ymbMiF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/woq313rsk7q2puubxxy6.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Modern Application Lifecycle Management (ALM)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;As you can see, we have tools and processes for each major step of ALM. Most of these elements have been covered in previous articles in this series from IDEs/CLIs/extensions to help developers manage code to automated unit tests.&lt;/p&gt;
&lt;h1&gt;
  
  
  Continuous Integration/Deployment for Salesforce
&lt;/h1&gt;

&lt;p&gt;In my opinion, a major key for Salesforce administrators and developers is to shift away from a limiting “org-based” development model where the production and sandbox orgs themselves serve as the source of truth of the application to a source-driven development model.  In a source-driven model, the source code, managed in git, serves as the source of truth.  After adopting this concept, it becomes much easier to work with ALM and avoid some of the problems mentioned above.&lt;/p&gt;

&lt;p&gt;An example of such source-driven development and automation can be seen in the diagram below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--FPJuGqoT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ka2wgrua5viz37g8unbp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--FPJuGqoT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ka2wgrua5viz37g8unbp.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Source-driven Automation&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Using a git repository that houses the Salesforce application’s code, we can manage the environments (orgs) and branches of the application to avoid things like overwriting code and allow for precise tracking of features and fixes.&lt;/p&gt;

&lt;p&gt;Rather than simply deploying changes directly from sandbox to production with a difficult-to-track and impossible-to-rollback changeset, a source drive automation could proceed as follows:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The admin/developer checks out a new feature branch from the most up-to-date branch&lt;/li&gt;
&lt;li&gt;The admin/developer makes their changes to the app in a sandbox or scratch org and then verifies and commits their changes to their feature branch&lt;/li&gt;
&lt;li&gt;They then make a “pull request” to an upstream branch such as an integration or QA/UAT branch that is tied to a dedicated integration or QA sandbox (typically a partial or full copy).  In this step, GitHub does some magic and compares the pull request to the target branch and detects if there are any conflicts in the code that need to be resolved before merging the pull request.  Typically you’ll also want to require the developers to write a summary of the pull request and have reviewers review the pull request before merging it.  This is where you can prevent developers from overwriting code as well as other quality checks.&lt;/li&gt;
&lt;li&gt;Automated unit and regression tests can also be invoked around this step to make sure that all automated tests pass.&lt;/li&gt;
&lt;li&gt;The updated codebase can then be deployed to the QA or UAT Salesforce environment for demos and end-user testing.&lt;/li&gt;
&lt;li&gt;If all passes there, then you can version the QA/Integration branch and merge it into the production branch that is tied to the Production environment.  Here, you can have a continuous deployment or continuous integration job automatically deploy the updates from the branch to the target production org to save time deploying things manually.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;While this list may seem longer than a simpler deployment model, using source management tools like Github and Github Actions and continuous integration/continuous deployment (CI/CD) or DevOps workflow tools like&lt;a href="https://www.copado.com/"&gt; Copado&lt;/a&gt; and&lt;a href="https://gearset.com/"&gt; Gearset&lt;/a&gt; can significantly automate and streamline this process.  Sometimes the deployment of certain functionality may involve not just metadata but data in the objects themselves, such as when important configuration information in managed packages are stored in the object data layer.  In this case, Github wouldn’t be able to help with tracking and deploying the data itself.  And for these situations, I like to use tools like&lt;a href="https://prodly.co/"&gt; Prodly&lt;/a&gt; and&lt;a href="https://www.sfapex.com/"&gt; sfAPEX&lt;/a&gt; to help manage deployments that involve actual data.&lt;/p&gt;
&lt;h1&gt;
  
  
  Heroku Deployments and Heroku Flow
&lt;/h1&gt;

&lt;p&gt;In a previous article, we deployed our Heroku application from the CLI from our local repository directly to Heroku.  To involve Github workflows into this process and take advantage of all of the source control features of Github, we can create an integration between Heroku git and Github so that once our code changes get pulled to a certain branch, such as the production or master branch. The updates get deployed automatically to our live Heroku app thus automating a repetitive aspect of the developer workflow.&lt;/p&gt;

&lt;p&gt;To make this magic happen, we can use a feature of Heroku called&lt;a href="https://www.heroku.com/flow"&gt; Heroku Flow&lt;/a&gt;.  Heroku Flow, compared to Github Actions, is “more opinionated.”  In other words, setting up Heroku Flow is easier to automate deployments in the particular way that Heroku Flow works, but Github Actions has the possibility to be more customizable and deviate from the way Heroku Flow works.  However, in my opinion, Heroku Flow is likely to work for the vast majority of CI/CD workflows.&lt;/p&gt;

&lt;p&gt;To set up the basics of Heroku Flow to deploy apps directly from a GitHub repo, follow these steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Set up a Github repo for the code for the app.&lt;/li&gt;
&lt;li&gt;Log into the app on Heroku and go to the Deploy tab.&lt;/li&gt;
&lt;li&gt;On the Deploy tab, you’ll see under the Deployment method area an option to ‘Connect to Github’.  This is how we’ll get Heroku talking to the Github repo for the app.&lt;/li&gt;
&lt;li&gt;Click on ‘Connect to Github’ and authorize Heroku to connect with your Github credentials.&lt;/li&gt;
&lt;li&gt;After authorizing Heroku to Github, search for the repository you want to connect to and hit the ‘Connect’ button.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--EEsnB_xa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9gybo0ldmawcm83tl2st.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--EEsnB_xa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9gybo0ldmawcm83tl2st.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Connect to Github&lt;/em&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;After connecting to the desired Github repo, the ‘Automatic deploys’ and ‘Manual deploy’ sections of the page become available.&lt;/li&gt;
&lt;li&gt;Under the ‘Automatic deploys’ area, select the branch to deploy (typically master or Production) and then hit the ‘Enable Automatic Deploys’ button.  If you have any tests as part of your CI process (and you should), you can check the ‘Wait for CI to pass before’ checkbox to instruct Automatic deploys to wait for the CI tests to pass before allowing each automatic deploy.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mI5R8YOS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9bboi9vqne97ov6ddrdi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mI5R8YOS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9bboi9vqne97ov6ddrdi.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Automatic Deploys&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;After this last step, all of the approved commits and pull requests that merge into the selected branch will automatically deploy to the Heroku app.  Viola!  One piece of the DevOps lifecycle automated.&lt;/p&gt;

&lt;p&gt;If for some reason, a manual deploy is necessary, go to the ‘Manual deploy’ area and manually deploy a branch from the repository.&lt;/p&gt;
&lt;h1&gt;
  
  
  Creating a ‘Deploy to Heroku’ Button on Github
&lt;/h1&gt;

&lt;p&gt;In addition to the Heroku Flow automated deployments, we can also add a handy ‘Deploy to Heroku’ button to our Github repository to allow deployments to Heroku directly from the Github repository.  This allows anyone with access to the repo to quickly deploy the app to Heroku with a click of a button!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--srs0UuD_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mbxcr6266qkzsmhzaej5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--srs0UuD_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mbxcr6266qkzsmhzaej5.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are few prerequisites to set up before we get our button working.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;    First we need an app.json file that contains descriptions and attributes of our app and optionally all of the ‘atoms’ of the application.  If you do add atoms to the app.json file, then these atoms will be automatically created when the button is invoked—a very handy feature.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;An app.json file might look something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "name": "Node.js Sample",
  "description": "A barebones Node.js app using Express",
  "repository": "https://github.com/heroku/node-js-getting-started",
  "logo": "https://node-js-sample.herokuapp.com/node.png",
  "keywords": ["node", "express", "static"]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;    Once we have the app.json file set up, the next step is to render the button itself.  The button can be rendered using an implicit template markdown or raw HTML.  The implicit template is handy for embedding the button in the readme section of the Github repo.  Use the HTML version if you’re rendering the button somewhere else like on a web page for the app.  The implicit template is a bit more convenient because it can use the referrer header from the repo when someone clicks on the button from Github and avoids hard-coding the specific repository URL into the button.  This allows forks and branches of the repository to work properly without a change to the button href URL itself.  You can also add URL parameters to the buttons.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;An example of an implicit template with URL parameters:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[![Deploy](https://www.herokucdn.com/deploy/button.svg)](https://heroku.com/deploy?template=https://github.com/heroku/node-js-getting-started)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;An example of the HTML version with URL parameters:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;a href="https://heroku.com/deploy?template=https://github.com/heroku/node-js-getting-started"&amp;gt;
  &amp;lt;img src="https://www.herokucdn.com/deploy/button.svg" alt="Deploy"&amp;gt;
&amp;lt;/a&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After adding the button code to the readme file in the repo or to the website, clicking on the button will automatically take you to the ‘deploy app’ menu in Heroku and you’re off to the races deploying the app to Heroku.&lt;/p&gt;

&lt;p&gt;Another powerful feature of the ‘Deploy to Heroku’ button method is the ability to add and pre-fill different environment variables and create variations of your Heroku app deployment by populating different environment variables that you have set up for your app.&lt;/p&gt;

&lt;h1&gt;
  
  
  Heroku Pipelines
&lt;/h1&gt;

&lt;p&gt;A common requirement for DevOps is to have a single app living on multiple separate environments such as one for staging and one for production.  To fulfill and automate this use case, we can use Heroku Pipelines.  To get started creating a new pipeline, from the main menu in Heroku, select the ‘New’ dropdown and select ‘Create new pipeline’.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8jZspaKY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xwa2z5hm2mbpu10bkcfs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8jZspaKY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xwa2z5hm2mbpu10bkcfs.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then we will need to fill out the information for our new pipeline and connect it to a Github repo.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Zf3egJLm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o4bpfdwtltie0xlpmw1b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Zf3egJLm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o4bpfdwtltie0xlpmw1b.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Create new pipeline&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Once we hit ‘Create pipeline’ we can start setting up the pipeline.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--dqKTD3Pv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zen88vyretuonmoufglz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dqKTD3Pv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zen88vyretuonmoufglz.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;From here, we can add our app to the Staging step of our pipeline and connect our Github repo’s staging branch and also set up automatic deployments as we did earlier.  This makes it so that each commit/merged pull request to that branch will automatically deploy to the staging app on our pipeline.  We can then connect the live branch of our app to the Production step of the pipeline but NOT enable automatic deployments.  The whole point is that we want to first validate that everything is working in the staging environment before going ahead and promoting to production.&lt;/p&gt;

&lt;p&gt;Finally, the ‘Enable Review Apps’ functionality is very useful for creating a test app each time a pull request is created against the branch.  Setting up and enabling Review Apps on Heroku this way will allow you to conveniently create a test app for the pull request so that you and any reviewers of the pull request can test out the new features and perform any manual regression tests needed before approving the pull request.  Then, once the pull request is merged into a branch that has been set up with Automatic Deployments, it will get automatically deployed to the next step of our pipeline.&lt;/p&gt;

&lt;p&gt;And with that, some really nice automation has been added to our app’s DevOps processes so that the developers have ‘easy buttons’ that do the heavy lifting on some of these repetitive tasks allowing the developers to focus on the build aspects of the app!&lt;/p&gt;

&lt;h1&gt;
  
  
  Concluding Thoughts
&lt;/h1&gt;

&lt;p&gt;For Salesforce admins and developers, I think that the ease of configuration and adding new functionality to the Salesforce application has gotten us somewhat ‘spoiled’ versus a more traditional DevOps process.  As a result, I have noticed some resistance in adopting a more defined DevOps process because, in the beginning, it has a tendency to slow things down for the admins and developers who might be used to quickly deploying new features and changes from sandbox to production or even making the changes in the production environment itself. &lt;/p&gt;

&lt;p&gt;However, the Salesforce or Heroku app will eventually increase in size and scope and eventually outgrow the simple processes in place when it was just one or two people working on it.  And before that happens, you’re going to want to set up a sustainable and future-proofed application lifecycle management process or struggle with every single release trying to manage all of the steps of the process and its dependencies manually.&lt;/p&gt;

&lt;p&gt;And since this is the last article of this series, I want to thank everyone for reading my content and following me along in this journey in learning more about modern application development on the Salesforce and Heroku ecosystems!&lt;/p&gt;

&lt;p&gt;For more information, Trailhead modules, and advanced topics related to Salesforce and Heroku app deployment and packaging, check out the links to the resources below:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;a href="https://trailhead.salesforce.com/en/content/learn/modules/sfdx_travis_ci"&gt;Continuous Integration Using Salesforce DX&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://developer.salesforce.com/blogs/2019/05/continuous-integration-with-salesforce-dx.html"&gt;Sample Starter Kit for CI/CD Automation for Salesforce Projects&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://devcenter.heroku.com/articles/github-integration"&gt;Automatic Deployments with GitHub&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://devcenter.heroku.com/articles/heroku-button"&gt;Creating a Deploy to Heroku Button&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://devcenter.heroku.com/articles/pipelines"&gt;Heroku Pipelines&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://devcenter.heroku.com/articles/github-integration-review-apps"&gt;Review Apps&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://docs.github.com/en/actions"&gt;Github Actions&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://github.com/trailheadapps/easy-spaces-lwc/tree/develop/.github/workflows"&gt;Sample Workflow Using Github Actions&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://developer.salesforce.com/blogs/2020/01/using-salesforce-dx-with-github-actions.html"&gt;Salesforce DX with Github Actions&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://github.com/scolladon/sfdx-git-delta"&gt;SFDX Git Delta Deploy CLI Plugin&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you haven’t already joined the official Chatter group for this series, I certainly recommend doing so.  This will give you the full value of the experience; in the group, you can also pose questions and start discussions with other members.  There are often valuable discussions and additional references available, such as presentation slides and other resources and references.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://sforce.co/34Ld7xz"&gt;https://sforce.co/34Ld7xz&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;About me:  I’m an 11x certified Salesforce professional who’s been running my own Salesforce consultancy for several years. If you’re curious about my backstory on accidentally turning into a developer and even competing on stage on a quiz show at one of the Salesforce conventions, you can read&lt;a href="http://green.salesforce.com/blog/2017/04/accidental-developer-to-dst17-finalist.html"&gt; this article&lt;/a&gt; I wrote for the Salesforce blog a few years ago.&lt;/p&gt;

</description>
      <category>salesforce</category>
      <category>heroku</category>
      <category>github</category>
    </item>
    <item>
      <title>Deploying Salesforce and Heroku Apps with Ease</title>
      <dc:creator>Jason Sun</dc:creator>
      <pubDate>Fri, 26 Feb 2021 21:58:45 +0000</pubDate>
      <link>https://dev.to/jasonomnivo/deploying-salesforce-and-heroku-apps-with-ease-1d0g</link>
      <guid>https://dev.to/jasonomnivo/deploying-salesforce-and-heroku-apps-with-ease-1d0g</guid>
      <description>&lt;h2&gt;
  
  
  (Heroku and Salesforce - From Idea to App, Part 12)
&lt;/h2&gt;

&lt;p&gt;This is the 12th article documenting what I’ve learned from a series of&lt;a href="https://trailhead.salesforce.com/live/videos/a2r3k000001n2Ig/modern-app-development-on-salesforce/?ref=hackernoon.com"&gt; 13 Trailhead Live video sessions on Modern App Development on Salesforce and Heroku&lt;/a&gt;.  In these articles, we’re focusing on how to combine Salesforce with&lt;a href="https://www.heroku.com/"&gt; Heroku&lt;/a&gt; to build an “eCars” app—a sales and service application for a fictitious electric car company (“Pulsar”).  eCars allows users to customize and buy cars, service techs to view live diagnostic info from the car, and more. In case you missed my previous articles, you can find the links to them below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/jasonomnivo/modern-app-development-on-salesforce-and-heroku-206j"&gt;Modern App Development on Salesforce and Heroku&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/jasonomnivo/jumping-into-heroku-development-48ep"&gt;Jumping into Heroku Development&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/jasonomnivo/data-modeling-in-salesforce-and-heroku-data-services-569e"&gt;Data Modeling in Salesforce and Heroku Data Services&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/jasonomnivo/building-front-end-app-experiences-with-clicks-not-code-2m6e"&gt;Building Front-End App Experiences with Clicks, Not Code&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/jasonomnivo/custom-app-experiences-with-lightning-web-components-4i39"&gt;Custom App Experiences with Lightning Web Components&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/jasonomnivo/lightning-web-components-events-and-lightning-message-service-21b8"&gt;Lightning Web Components, Events and Lightning Message Service&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/jasonomnivo/automating-business-processes-using-salesforce-flows-and-apex-923"&gt;Automating Business Processes Using Salesforce Flows and APEX&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/jasonomnivo/scale-salesforce-apps-using-microservices-on-heroku-43k7"&gt;Scale Salesforce Apps Using Microservices on Heroku&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/jasonomnivo/more-scaling-salesforce-apps-using-heroku-microservices-3k1f"&gt;More Scaling Salesforce Apps Using Heroku Microservices&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/jasonomnivo/javascript-unit-testing-24k7"&gt;Javascript Unit Testing&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/jasonomnivo/apex-unit-testing-on-salesforce-1968"&gt;APEX Unit Testing on Salesforce&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Just as a quick reminder:  I’ve been following this Trailhead Live video series to brush up and stay current on the latest app development trends on these platforms that are key for my career and business.  I’ll be sharing each step for building the app, what I’ve learned, and my thoughts from each session.  These series reviews are both for my own edification as well as for others who might benefit from this content.&lt;/p&gt;

&lt;p&gt;The Trailhead Live sessions and schedule can be found here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://trailhead.salesforce.com/live"&gt;https://trailhead.salesforce.com/live&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Trailhead Live sessions I’m writing about can also be found at the links below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://trailhead.salesforce.com/live/videos/a2r3k000001n2Jj/modern-app-development-on-salesforce"&gt;https://trailhead.salesforce.com/live/videos/a2r3k000001n2Jj/modern-app-development-on-salesforce&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/playlist?list=PLgIMQe2PKPSK7myo5smEv2ZtHbnn7HyHI"&gt;https://www.youtube.com/playlist?list=PLgIMQe2PKPSK7myo5smEv2ZtHbnn7HyHI&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Last Time…
&lt;/h1&gt;

&lt;p&gt;Last time, we went through unit testing of Salesforce Apex code and learned about the unique unit testing framework that the Salesforce platform provides.&lt;/p&gt;

&lt;p&gt;Now that we’ve built all the pieces of our eCars app, it’s time to move onto the exciting part: deploying the app so it can be accessed and enjoyed by our end users!  We’ll cover packaging and deployments for both JavaScript as well as Salesforce apps.&lt;/p&gt;

&lt;h1&gt;
  
  
  Creating JavaScript Packages with npm
&lt;/h1&gt;

&lt;p&gt;We’re going to start off with how to create packages for our Javascript application using npm.  It’s important to know that npm is the JavaScript package registry—where all of the Node.js and JavaScript packages live.  It’s basically the world’s biggest vault of useful app development libraries, utilities and other useful things you might need to import to your project in order to generate charts, render PDFs, or create 3D graphics.  Everything on npm is open-source, so you and other developers are actively contributing to the open-source ecosystem when packaging with npm.&lt;/p&gt;

&lt;p&gt;To get started with npm, you’ll have to first register for an account at&lt;a href="https://npmjs.com/signup"&gt; https://npmjs.com/signup&lt;/a&gt;.  Enabling two-factor authentication is highly recommended for your npm account. There have been some nightmare stories in the past where some people’s npm accounts have become compromised and bad actors were able to publish versions of their packages with malicious code in it!&lt;/p&gt;

&lt;p&gt;Once you have npm up and running, from the command line, you can execute a few steps to start preparing your npm package.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1.     Create a package.json file by running `'npm init' `from the VS Code terminal
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The package.json file contains all the metadata for your app such as the name, the components, dependencies, etc.  The above command will take you to a wizard-like process in the command line to fill out some information to generate your package.json file.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;2.     Add any secret files to the `.npmignore `file
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This file is similar to .gitignore or .forceignore and will prevent any specified files from being published to the public npm registry.  Any files that contain secrets, keys, or other sensitive information should be added to the file so they aren’t exposed to the public.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;3.     Preview the package with the `'npm pack'` command to view what is going to be published
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This is a good way to check if there are any files you need to add to the &lt;code&gt;.npmignore&lt;/code&gt; file in step 2.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;4.     Login with `'npm login'`  if you are not already logged in and use `'npm publish'`   to publish the package and watch the magic happen
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;At some point, you’ll likely want to update your package, make improvements, fix bugs, or otherwise push an update to your package.  This process is pretty simple and after making your needed updates, you can push them out with the following process:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1.     Run `'npm version patch/minor/major'` to bump your package to another version


2.     Run `'npm publish'` again to publish your new package version
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;When versioning your packages, you should follow the “Semantic Versioning” or semver nomenclature with a format that resembles 2.0.1 or MAJOR.MINOR.PATCH.  Generally, this means the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  MAJOR version when you make incompatible API changes,&lt;/li&gt;
&lt;li&gt;  MINOR version when you add functionality in a backward-compatible manner,&lt;/li&gt;
&lt;li&gt;  PATCH version when you make backward-compatible bug fixes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Semver isn’t just for npm or JavaScript packages; it should be followed for any kind of app package versioning including unmanaged and managed Salesforce packages.&lt;/p&gt;

&lt;p&gt;For more about semver, check out this link:&lt;a href="https://semver.org/"&gt; https://semver.org/&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Types of npm Packages and Naming Guidelines
&lt;/h1&gt;

&lt;p&gt;There are three major types of npm packages, each with some distinct features and use cases.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Unscoped Public Packages&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Available to all users&lt;/li&gt;
&lt;li&gt;  Have unique names&lt;/li&gt;
&lt;li&gt;  Examples:

&lt;ul&gt;
&lt;li&gt;  Express&lt;/li&gt;
&lt;li&gt;  Fastify&lt;/li&gt;
&lt;li&gt;  Moment&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are the common global, public packages that you will frequently come across when it comes to importing a particular package for your app.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scoped Public Packages&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Available to all users&lt;/li&gt;
&lt;li&gt;  Are published under a scoped namespace&lt;/li&gt;
&lt;li&gt;  Require an npm organization&lt;/li&gt;
&lt;li&gt;  Must have a unique name&lt;/li&gt;
&lt;li&gt;  Examples:

&lt;ul&gt;
&lt;li&gt;  @lwc/engine&lt;/li&gt;
&lt;li&gt;  @lwc/compiler&lt;/li&gt;
&lt;li&gt;  @heroku/foreman&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are often forked versions of unscoped public packages that may have some unique modifications to them to suit a particular use.  They’re scoped in their own namespace so as to be isolated from the unscoped public packages.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Private Packages&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Available to users of a paid npm enterprise organization&lt;/li&gt;
&lt;li&gt;  Can be org scoped, user scoped, or have no scope&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Private packages are used when an organization wants all the benefits of npm but is developing packages that will not be published in the public npm registry.  These could be home-grown apps that are only used for a particular organization.&lt;/p&gt;

&lt;p&gt;Now that we know about the different types of packages, let’s go over some package naming guidelines. In general, package names should abide by the following guidelines:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Names are unique&lt;/li&gt;
&lt;li&gt;  Names are descriptive&lt;/li&gt;
&lt;li&gt;  Names meet&lt;a href="https://docs.npmjs.com/package-name-guidelines"&gt; npm name policy guidelines&lt;/a&gt; and do not use offensive or trademarked words&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In case you’re choosing a name for an unscoped package, you should also:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Choose a name that is not already owned by someone else&lt;/li&gt;
&lt;li&gt;  Not be spelled in a similar way to another package (so as to avoid confusion)&lt;/li&gt;
&lt;li&gt;  Not confuse others about the authorship of the package&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Follow the guidelines above and you’ll avoid receiving any nasty letters from law firms!&lt;/p&gt;

&lt;h1&gt;
  
  
  Salesforce Development Models and Packaging
&lt;/h1&gt;

&lt;p&gt;When I was starting out as a Salesforce administrator, the concepts of “deployment” and “packaging” did not come up very often.  I was usually configuring things using point-and-click methods directly in the production environment (gasp!).  Every now and then, I might deploy an APEX class or trigger from a sandbox environment to the production environment using the Changesets tool. That was because admins had to deploy those types of custom code from a sandbox at that time in order to get them into production.  As a result, most Salesforce administrators may be more familiar with the aforementioned process of customizing the org itself. This is referred to as “org development” or “unpackaged” development.  The other possible development model is “package development,” which you may only come across if you have created unmanaged, managed, or unlocked packages— perhaps in the course of creating a Salesforce app for distribution on the AppExchange.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RbmcWnpH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g2rlyei5q3hp9f7xhjn0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RbmcWnpH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g2rlyei5q3hp9f7xhjn0.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The key for each development model is in the “source of truth” for the application.  In org development—the one Salesforce folks are likely most familiar with—the org itself is the source of truth. That’s different from package development, where the source of truth is typically a git repository for the application’s code and metadata.&lt;/p&gt;

&lt;p&gt;When comparing to JavaScript app packaging, think of org development as a private package for use with that specific Salesforce org. Meanwhile, package development is more like creating a public package that’s intended for public use in other Salesforce orgs.&lt;/p&gt;

&lt;p&gt;Let’s say that you or your company want to become a Salesforce ISV and go for package development.  It’s then important to know all about Salesforce packaging and requirements.&lt;/p&gt;

&lt;p&gt;In general, Salesforce packages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Represent a container of metadata.  This includes all customizations and custom code&lt;/li&gt;
&lt;li&gt;  Must compile and validate in order to deploy to other orgs&lt;/li&gt;
&lt;li&gt;  Usually require you to map a package to a directory in the project workspace (when packaging with Salesforce DX Source format)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One obvious advantage of unpackaged/org development on Salesforce is that it’s fast and gives you immediate gratification. In other words, the org that’s being used gets to realize the benefits of the development changes immediately.  However, it’s important to also realize how beneficial package development can be, despite having more steps and creating some overhead tasks.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LmAVN0iL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d4rde2nh5zktu40x5vyb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LmAVN0iL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d4rde2nh5zktu40x5vyb.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Some benefits of package-based development&lt;/p&gt;

&lt;p&gt;In addition to the benefits shown above, I would also argue that package development forces Salesforce admins and developers to adopt a sense of discipline when it comes to being organized and planning for the future maintenance, scalability, and iterability of the application.  Unpackaged development, while fast, can end up creating a great deal of technical debt that eventually has to be paid back once the org becomes difficult to maintain and manage.&lt;/p&gt;

&lt;p&gt;There are different types of Salesforce packages as well.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Managed Packages –&lt;/strong&gt; These are the types of packages that are geared towards Salesforce ISV partners and publishers of apps on the AppExchange.  With 2GP managed packages, the ISVs also get additional features like push upgrades and access to the License Management tool.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Unlocked Packages –&lt;/strong&gt; Unlocked packages are primarily used to address the packaging needs of individual customers and their Salesforce orgs.  This is the ideal fit for those Salesforce orgs that are not going to publish to the AppExchange but want to adopt a package-based approach for the benefits mentioned above.&lt;/p&gt;

&lt;p&gt;Under the category of &lt;strong&gt;Unlocked Packages&lt;/strong&gt;, there are two subtypes also.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Org Independent –&lt;/strong&gt; Org independent packages are packages that don’t have dependencies on the org itself. They can support multiple different orgs while still maintaining the core business process and functionality.  Dependencies are validated during package creation and dependencies on other packages can be set.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Org Dependent (Runtime Packages) –&lt;/strong&gt; Org dependent packages might be used for massive orgs where untangling the dependencies may not be an option.  The dependencies are validated during package installation instead of at package creation and can depend on other packages as well as the target org itself.  It’s recommended to use sandboxes with a source tracking tool with these packages.&lt;/p&gt;

&lt;h1&gt;
  
  
  Creating a Salesforce Package in VS Code
&lt;/h1&gt;

&lt;p&gt;When working with SalesforceDX and VS Code, an sfdx-project.json file is created automatically that contains some packaging information for the app.  This is just like the package.json file we have for JavaScript applications deployed on npm.  Note that you can add a “namespace” to the file. Doing so will add a namespace prefix to all of the components in the package such as custom fields, objects, APEX classes, etc.  This step will ensure that the package components will not collide with metadata in target installation orgs. It will also make the package components easy to spot and identify once they are installed.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_zvRNHHA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lhmym7ivxag4g7b12r3s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_zvRNHHA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lhmym7ivxag4g7b12r3s.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After the app is ready to be packaged, running the following command on the command line will initialize the Salesforce package and update the sfdx-project.json file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sfdx force:package:create -n [name of the package] -t [type of package] -r [directory of package]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--816nlCbl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/luky5h766b223lahpt90.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--816nlCbl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/luky5h766b223lahpt90.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
The sfdx-project.json file after running the force📦create command&lt;/p&gt;

&lt;p&gt;As you can see, we have the first version of the package initialized. In this step, a package ID gets generated.  Next, if we wanted to bump a version of the app, we would use the following comment.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;force:package:version:create - p [package id] -x/-k [optional password]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that the -k with optional password attribute will lock the package with a specific password, whereas using the -x parameter indicates that there is no password and that this will be more of an open-source project.&lt;/p&gt;

&lt;p&gt;This particular command/process takes some time to complete because it’s actually creating a scratch org, compiling all of the metadata, checking dependencies, and running all APEX tests to make sure that everything validates.  Once it does though, you’ll have a beautiful and updated sfdx-project.json file with all of the correct package information!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wb9WQOEo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hb14da60l8zo5icrexr2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wb9WQOEo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hb14da60l8zo5icrexr2.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
Packaged and gift-wrapped eCar application&lt;/p&gt;

&lt;p&gt;The installation URL is where people will go to actually install the package into their respective orgs.  Now, we can offer the eCars app to Salesforce orgs across the entire ecosystem!&lt;/p&gt;

&lt;h1&gt;
  
  
  Concluding Thoughts
&lt;/h1&gt;

&lt;p&gt;As mentioned earlier, Salesforce admins and developers may not naturally approach things from a package-based development perspective.  However, the whole concept of organizing code and metadata and their respective dependencies into a neat and cohesive container can pay dividends. Those payoffs exist even if the organization is not planning to publish their solution on the AppExchange.  This is super relevant, especially for orgs that grow in size and complexity.  Adopting a package-based approach as soon as things start getting complicated will ensure that the discipline inherent in package-based development will keep the org scalable, maintainable, and manageable.  I have seen many orgs bury themselves beneath a mountain of technical debt that has resulted from undisciplined development and configuration.  Hopefully, more members of the Salesforce ecosystem will start adopting package-based development with Unlocked Packages!&lt;/p&gt;

&lt;p&gt;For more information, Trailhead modules, and advanced topics related to Salesforce and Heroku app deployment and packaging, check out the links to the resources below:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;a href="https://docs.npmjs.com/creating-node-js-modules"&gt;Creating&lt;/a&gt;&lt;span&gt; Node.js Modules&lt;/span&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://docs.npmjs.com/cli/v6/commands/npm-publish"&gt;npm publish Documentation&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://docs.npmjs.com/cli/v6/commands/npm-version"&gt;npm version Documentation&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://trailhead.salesforce.com/en/content/learn/modules/unlocked-packages-for-customers"&gt;Unlocked Packages for Customers&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://trailhead.salesforce.com/en/content/learn/modules/sfdx_dev_model"&gt;Package Based Development Model&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://www.youtube.com/watch?v=xJNmHOtIgO0"&gt;Successfully Creating Unlocked Packages&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://trailhead.salesforce.com/en/content/learn/projects/quick-start-explore-the-easyspaces-sample-app"&gt;Explore: Easy Spaces Sample Gallery App&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the next article, we’ll go through the final topic in the series: managing the app development lifecycle and automating developer workflows.&lt;/p&gt;

&lt;p&gt;If you haven’t already joined the official Chatter group for this series, I certainly recommend doing so.  This will give you the full value of the experience; in the group, you can also pose questions and start discussions with other members.  There are often valuable discussions and additional references available, such as presentation slides and other resources and references.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://sforce.co/34Ld7xz"&gt;https://sforce.co/34Ld7xz&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;About me:  I’m an 11x certified Salesforce professional who’s been running my own Salesforce consultancy for several years. If you’re curious about my backstory on accidentally turning into a developer and even competing on stage on a quiz show at one of the Salesforce conventions, you can read&lt;a href="http://green.salesforce.com/blog/2017/04/accidental-developer-to-dst17-finalist.html"&gt; this article&lt;/a&gt; I wrote for the Salesforce blog a few years ago.&lt;/p&gt;

</description>
      <category>heroku</category>
      <category>salesforce</category>
      <category>javascript</category>
      <category>npm</category>
    </item>
    <item>
      <title>Apex Unit Testing on Salesforce</title>
      <dc:creator>Jason Sun</dc:creator>
      <pubDate>Fri, 26 Feb 2021 21:28:39 +0000</pubDate>
      <link>https://dev.to/jasonomnivo/apex-unit-testing-on-salesforce-1968</link>
      <guid>https://dev.to/jasonomnivo/apex-unit-testing-on-salesforce-1968</guid>
      <description>&lt;h2&gt;
  
  
  &lt;strong&gt;(Heroku and Salesforce - From Idea to App, Part 11)&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;This is the eleventh article documenting what I’ve learned from a series of&lt;a href="https://trailhead.salesforce.com/live/videos/a2r3k000001n2Ig/modern-app-development-on-salesforce/?ref=hackernoon.com" rel="noopener noreferrer"&gt; 13 Trailhead Live video sessions on Modern App Development on Salesforce and Heroku&lt;/a&gt;. In these articles, we’re focusing on how to combine Salesforce with&lt;a href="https://www.heroku.com/" rel="noopener noreferrer"&gt; Heroku&lt;/a&gt; to build an “eCars” app—a sales and service application for a fictitious electric car company (“Pulsar”) that allows users to customize and buy cars, service techs to view live diagnostic info from the car, and more. In case you missed my previous articles, you can find the links to them below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/jasonomnivo/modern-app-development-on-salesforce-and-heroku-206j"&gt;Modern App Development on Salesforce and Heroku&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/jasonomnivo/jumping-into-heroku-development-48ep"&gt;Jumping into Heroku Development&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/jasonomnivo/data-modeling-in-salesforce-and-heroku-data-services-569e"&gt;Data Modeling in Salesforce and Heroku Data Services&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/jasonomnivo/building-front-end-app-experiences-with-clicks-not-code-2m6e"&gt;Building Front-End App Experiences with Clicks, Not Code&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/jasonomnivo/custom-app-experiences-with-lightning-web-components-4i39"&gt;Custom App Experiences with Lightning Web Components&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/jasonomnivo/lightning-web-components-events-and-lightning-message-service-21b8"&gt;Lightning Web Components, Events and Lightning Message Service&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/jasonomnivo/automating-business-processes-using-salesforce-flows-and-apex-923"&gt;Automating Business Processes Using Salesforce Flows and APEX&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/jasonomnivo/scale-salesforce-apps-using-microservices-on-heroku-43k7"&gt;Scale Salesforce Apps Using Microservices on Heroku&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/jasonomnivo/more-scaling-salesforce-apps-using-heroku-microservices-3k1f"&gt;More Scaling Salesforce Apps Using Heroku Microservices&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/jasonomnivo/javascript-unit-testing-24k7"&gt;Javascript Unit Testing&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Just as a quick reminder: I’ve been following this Trailhead Live video series to brush up and stay current on the latest app development trends on these platforms that are key for my career and business. I’ll be sharing each step for building the app, what I’ve learned, and my thoughts from each session. These series reviews are both for my own edification as well as for others who might benefit from this content.&lt;/p&gt;

&lt;p&gt;The Trailhead Live sessions and schedule can be found here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://trailhead.salesforce.com/live" rel="noopener noreferrer"&gt;https://trailhead.salesforce.com/live&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Trailhead Live sessions I’m writing about can also be found at the links below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://trailhead.salesforce.com/live/videos/a2r3k000001n2Jj/modern-app-development-on-salesforce" rel="noopener noreferrer"&gt;https://trailhead.salesforce.com/live/videos/a2r3k000001n2Jj/modern-app-development-on-salesforce&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/playlist?list=PLgIMQe2PKPSK7myo5smEv2ZtHbnn7HyHI" rel="noopener noreferrer"&gt;https://www.youtube.com/playlist?list=PLgIMQe2PKPSK7myo5smEv2ZtHbnn7HyHI&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Last Time…&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Last time we explored unit testing with Javascript and jest.  This time we are focusing on unit testing again but for the Salesforce platform.&lt;/p&gt;

&lt;p&gt;For some, automated unit testing is an essential part of the application development process and a key component to making sure that code is running and behaving as expected.  For some (and I’ve been guilty of this in the past), unit tests in Salesforce is that annoying gatekeeper that stops me from deploying my custom APEX code until I’ve satisfied the 75% code coverage requirement.  Hopefully, after this session, we can change the perception of unit tests as a tool that greatly helps with our application development and maintenance processes as opposed to some kind of adversary.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;A Primer on Unit Testing&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;What is “unit testing” exactly and what’s different about unit testing versus other testing methods like regression testing or smoke testing?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  The “unit” part refers to the fact that the testing is verifying that a discrete method in the code, functionality or automation is working as intended separately from other dependencies.  So if you have a trigger handler with several methods, you might write unit tests that target those specific individual methods as opposed to testing the entire class.&lt;/li&gt;
&lt;li&gt;  The “testing” part is self-explanatory and just refers to the fact that you’re making sure that the method in code, functionality, or automation is working as expected.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzb8bt4uokwzg8iza7sha.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzb8bt4uokwzg8iza7sha.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Unit tests in a nutshell&lt;/p&gt;

&lt;p&gt;Here are some valuable benefits of unit tests:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Identify bugs easily and detect them earlier&lt;/li&gt;
&lt;li&gt;  Reduces the cost of fixing bugs and QA efforts&lt;/li&gt;
&lt;li&gt;  Makes code design and refactoring easier&lt;/li&gt;
&lt;li&gt;  Acts as a self-documenting set of test cases&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;However, these benefits are only fully realized when unit testing is implemented correctly and thoughtfully.  Oftentimes, I come across cases where unit testing has been implemented as an afterthought, only implemented with the bare minimum requirements to actually deploy the code, or in some of the worst-offending cases, completing cheating the process.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;A Framework for Unit Testing&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The framework we’re basing our unit test design here is the “AAA” or Arrange, Act, and Assert framework.  This framework doesn’t just apply to Salesforce code but can be used with any programming framework that supports unit tests.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqpxtahk4e4knbzvquax2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqpxtahk4e4knbzvquax2.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Salesforce examples for these would be something like as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Arrange&lt;/strong&gt;: Test data setup and inserting the objects/records needed for the unit test&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Act&lt;/strong&gt;: Call your methods or perform DML statements to run the code you want to test and capture the result&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Assert&lt;/strong&gt;: Create assert statements comparing the results you captured with expected results.  You typically want the test to error out or notify you in some way if the result you captured deviates from the expected result.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Unit testing is a core part of the Salesforce platform and Salesforce actually has specific requirements around unit tests and code coverage for deploying custom code to a production environment.  Some Salesforce-specific rules about testing are as follows:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Furhzhrbu62tv4a6gn57e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Furhzhrbu62tv4a6gn57e.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here are several additional details on the above bullet points as well.&lt;/p&gt;

&lt;p&gt;It’s nice that Salesforce actually uses its customers’ unit tests to help run regressions before each of their major releases since Salesforce instances can be highly customized with APEX code.  A release breaking my existing code has been exceedingly rare and a nice feature of APEX classes is that you can actually set the API versions of them to be on a prior Salesforce release and then only upgrade them to the latest version when you have also fully tested things on your own.&lt;/p&gt;

&lt;p&gt;This 75% code coverage requirement means that if you have 1000 lines of APEX code across the entire org, APEX test classes must simulate and run at least 750 of those lines of code in order for code updates or new code to be deployed.  This is where I’ve seen some pretty clever workarounds (read: cheats) that I won’t share, but just know that they should never be used and you should always strive to write legitimate and well-thought-out unit tests.&lt;/p&gt;

&lt;p&gt;Having a variety of test cases makes the unit tests much more valuable since you are covering more edge cases with them.  As a result, they can alert you if some change to the system is introduced that impacts the code from performing as expected.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Positive tests&lt;/strong&gt; - is the code doing the right thing when it’s supposed to?&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Negative tests&lt;/strong&gt; - is the code not doing the thing when it’s NOT supposed to?&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Bulk tests&lt;/strong&gt; - does the code still run as expected if a large chunk of records updates at once?  Or do we hit some kind of CPU time-out error or SOQL query limit error?&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Profile/permission tests -&lt;/strong&gt; does the code run as expected when performed by users with different profiles and permissions?  Or is there some dependency created when a different profile tries to run it?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Finally, having a “Datafactory” class is a huge time-saver because having one place where valid test data can be generated and called by other test classes will come in handy.  For example, adding a new required field or validation to the system often causes unit tests to break because the test data does not account for the new field or validation rule.  Having a single place where you can update this saves you the trouble of having to change the test data setup for each of your affected unit test classes.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Creating an Apex Unit Test for the eCars App&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;For the eCars app that we’re building, the activity will be to write an APEX test class for the PdfCreateService that we used in the prior session to call a Heroku microservice for generating PDF documents.  The eCars code can be found at the&lt;a href="https://github.com/trailheadapps/ecars" rel="noopener noreferrer"&gt; linked Github repo&lt;/a&gt; and I have also included a link to the&lt;a href="https://github.com/trailheadapps/ecars/blob/main/force-app/main/default/classes/PdfCreateService.cls" rel="noopener noreferrer"&gt; specific PdfCreateService class&lt;/a&gt;.  If you have not gone through the exercise of pulling the code into a Salesforce Developer org or a scratch org, you’ll want to review some of the previous articles to take that pre-requisite step or follow the instructions in the Github repo on how to clone and deploy the application.&lt;/p&gt;

&lt;p&gt;You’ll see when examining the PdfCreateService class, it’s a pretty simple class with really one method, invokePdfCreateService, which takes a single parameter of a custom child class called ServiceInput and then makes an outbound HTTP callout to an external Heroku service.  The ServiceInput child class is also used to conveniently serialize JSON data for the Heroku service.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public with sharing class PdfCreateService {
    @AuraEnabled
    public static Boolean invokePdfCreateService(ServiceInput input) {
        HttpRequest req = new HttpRequest();
        req.setEndpoint('callout:Heroku_App/pdf');
        req.setMethod('POST');
        req.setHeader('Content-Type', 'application/json;charset=UTF-8');
        req.setTimeout(30000);
        req.setBody(JSON.serialize(input));


        Http http = new Http();
        HttpResponse res = http.send(req);


        if (res.getStatusCode() != 200) {
        String error =
            'The status code returned was not expected: ' +
            res.getStatusCode() +
            ' ' +
            res.getStatus();
        AuraHandledException e = new AuraHandledException(error);
        e.setMessage(error);
        throw e;
        }


        return true;
    }


    @testVisible
    class ServiceInput {
        @AuraEnabled
        public String exteriorColor { get; set; }
        @AuraEnabled
        public String interiorColor { get; set; }
        @AuraEnabled
        public String range { get; set; }
        @AuraEnabled
        public Decimal price { get; set; }
        @AuraEnabled
        public Id leadRecordId { get; set; }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first step of creating the unit test is to create a testDataFactory class to help generate the test data for the unit test.  This isn’t included in the Github repo as of today, so you’ll need to write one yourself, follow along &lt;a href="https://www.youtube.com/watch?v=Hi2A0N0dFFg&amp;amp;list=PLgIMQe2PKPSK7myo5smEv2ZtHbnn7HyHI&amp;amp;index=11" rel="noopener noreferrer"&gt;in the video&lt;/a&gt; to create one, or grab it from the solutions sheet that is posted in the Chatter discussion group linked at the end of this article.  The testDataFactory class will need to be able to create a test Lead, a test User, and also assign the test User the necessary permission set for the eCars app.&lt;/p&gt;

&lt;p&gt;We chose a bit of an interesting class to unit test because this class has a method that makes a webservice callout to an external service.  It would be quite a problem if our unit test &lt;em&gt;actually&lt;/em&gt; made a real webservice callout to the external service for two major reasons.  First, how would the external service know that it’s just a test and not a real callout and behave accordingly?  Second, we don’t know how the real external service might behave at any given moment like for example if there is service disruption and it’s down exactly when we are running our tests. &lt;/p&gt;

&lt;p&gt;As a result, Salesforce provides a way to actually create something called an HTTPMock class that is specifically used for testing methods that make web service callouts so that the expected behavior from the web service can be simulated or “mocked” in the HTTPMock class specifically for unit testing use cases.  There’s a specific interface called HttpCalloutMock that needs to be implemented as shown below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;global class YourHttpCalloutMockImpl implements HttpCalloutMock {
global HTTPResponse respond(HTTPRequest req) {
    // Create a fake response.
    // Set response values, and
    // return HTTPResponse object
}
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The goal for the eCars app would be to create a PdfCreateServiceMock class that we can use in our test classes to return a variety of HTTP responses and payloads.  In the video, Mohith provides an example of this but you should try to create your own version that might handle a number of other cases and responses.&lt;/p&gt;

&lt;p&gt;More information on testing HTTP callout methods and code samples can be found at the&lt;a href="https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_classes_restful_http_testing.htm" rel="noopener noreferrer"&gt; APEX Developer Guide&lt;/a&gt; as well as the&lt;a href="https://github.com/trailheadapps/apex-recipes" rel="noopener noreferrer"&gt; APEX recipes Github repo&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The last step, once we have our testDataFactory class and PdfCreateServiceMock class, is to create the actual TestPdfCreateService test class that will utilize both of the prior classes.  The test class should:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Create test data using our testDataFactory class, including one or more test users with different relevant profiles, as well as one or more test Lead records for running our test with&lt;/li&gt;
&lt;li&gt;  Assign permission sets to the user(s)&lt;/li&gt;
&lt;li&gt;  Have one or more test methods that run as our test users using the system.runAs method&lt;/li&gt;
&lt;li&gt;  Set data for the PdfCreateService.ServiceInput child class&lt;/li&gt;
&lt;li&gt;  Invoke the PdfCreateService.invokePdfCreateService with the ServiceInput object set previously&lt;/li&gt;
&lt;li&gt;  Call the PdfCreateServiceMock with the desired mocked up response&lt;/li&gt;
&lt;li&gt;  Run system.Assert statements to assert that the results from running the code match up to our expected results&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If all of the above criteria are fulfilled, once you run your test class using VSCode’s handy “runTest” command (comes with the Salesforce tools VSCode extension), you should get something like 90%+ test coverage.  Inspecting the classes in VSCode or the developer console will show which lines of code were covered in the test run vs. which ones were not.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faa740z0f4xecutyvqdp8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faa740z0f4xecutyvqdp8.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you weren’t able to get your test class built and solved on your own, that’s fine.  A solution for this should be posted in the Chatter discussion forum or you can ask for help there if you are stuck.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Unit Testing in APEX vs. Javascript&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;For those who are familiar with testing in Javascript but not in APEX or vice-versa, here are some key things to note.  The Apex language comes with system methods for writing apex unit tests classes.  For JavaScript, there are a number of different testing frameworks but Salesforce recommends using Jest for Lightning Web Components and LWC OSS because of its popularity, ease-of-use, and open-source framework.  Jest for Lightning Web Components is available at the&lt;a href="https://github.com/salesforce/sfdx-lwc-jest" rel="noopener noreferrer"&gt; sfdx-lwc-jest Github repo&lt;/a&gt;.  The following table draws some comparisons between the frameworks.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkv3ac91pfy3g1qjif33x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkv3ac91pfy3g1qjif33x.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Concluding Thoughts&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;As mentioned early on, unit testing in my opinion is one of the most underutilized and underappreciated components of building apps on the Salesforce platform.  I often see a great deal of technical debt that is built up that revolves around unit tests and APEX test classes.  It’s gotten to the point where if I’m jumping into a project where some coding has already been done, the first thing I do is run all of the org’s APEX test classes and see how many of the unit tests fail or provide insufficient coverage to certain classes.  I think this happens because too many people approach unit tests as a kind of barrier or box that you just have to check in order to get your code to deploy, but it doesn’t have to be this way.  If more developers approached unit tests as a helpful and core part of the code that they’re developing, well-built and designed unit tests can actually end up &lt;em&gt;saving&lt;/em&gt; on technical debt.&lt;/p&gt;

&lt;p&gt;For more information and advanced topics related to unit testing, check out the links to the resources below:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;a href="https://trailhead.salesforce.com/en/content/learn/modules/unit-testing-on-the-lightning-platform" rel="noopener noreferrer"&gt;Unit Testing On the Lightning Platform Trailhead Module&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://trailhead.salesforce.com/en/content/learn/modules/apex_testing" rel="noopener noreferrer"&gt;Apex Testing Trailhead Module&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_testing_stub_api.htm" rel="noopener noreferrer"&gt;Building a Mocking Framework with the Stub API&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://developer.salesforce.com/blogs/2018/05/month-of-testing-advanced-topics-in-salesforce-unit-testing-part-3-of-3.html" rel="noopener noreferrer"&gt;Advanced Apex Testing Blog&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_testing.htm" rel="noopener noreferrer"&gt;Testing Apex | Apex Developer Guide&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://github.com/trailheadapps/apex-recipes" rel="noopener noreferrer"&gt;Apex Recipes&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the next article, we’re going to go through the application package and deployments.&lt;/p&gt;

&lt;p&gt;If you haven’t already joined the official Chatter group for this series, I certainly recommend you do so. That way, you can get the full value of the experience and also pose questions and start discussions with the group. Oftentimes, there are valuable discussions and additional references available there such as the slides from the presentation and links to other resources and references.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://sforce.co/34Ld7xz" rel="noopener noreferrer"&gt;https://sforce.co/34Ld7xz&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;About me:  I’m an 11x certified Salesforce professional who’s been running my own Salesforce consultancy for several years. If you’re curious about my backstory on accidentally turning into a developer and even competing on stage on a quiz show at one of the Salesforce conventions, you can read&lt;a href="http://green.salesforce.com/blog/2017/04/accidental-developer-to-dst17-finalist.html" rel="noopener noreferrer"&gt; this article&lt;/a&gt; I wrote for the Salesforce blog a few years ago.&lt;/p&gt;

</description>
      <category>salesforce</category>
      <category>testing</category>
    </item>
    <item>
      <title>Javascript Unit Testing</title>
      <dc:creator>Jason Sun</dc:creator>
      <pubDate>Tue, 16 Feb 2021 17:26:41 +0000</pubDate>
      <link>https://dev.to/jasonomnivo/javascript-unit-testing-24k7</link>
      <guid>https://dev.to/jasonomnivo/javascript-unit-testing-24k7</guid>
      <description>&lt;h1&gt;
  
  
  (Heroku and Salesforce - From Idea to App, Part 10)
&lt;/h1&gt;

&lt;p&gt;This is the 10th article documenting what I’ve learned from a series of&lt;a href="https://trailhead.salesforce.com/live/videos/a2r3k000001n2Ig/modern-app-development-on-salesforce/?ref=hackernoon.com" rel="noopener noreferrer"&gt; 13 Trailhead Live video sessions on Modern App Development on Salesforce and Heroku&lt;/a&gt;. In these articles, we’re focusing on how to combine Salesforce with&lt;a href="https://www.heroku.com/" rel="noopener noreferrer"&gt; Heroku&lt;/a&gt; to build an “eCars” app—a sales and service application for a fictitious electric car company (“Pulsar”) that allows users to customize and buy cars, service techs to view live diagnostic info from the car, and more. In case you missed my previous articles, you can find the links to them below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/jasonomnivo/modern-app-development-on-salesforce-and-heroku-206j"&gt;Modern App Development on Salesforce and Heroku&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/jasonomnivo/jumping-into-heroku-development-48ep"&gt;Jumping into Heroku Development&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/jasonomnivo/data-modeling-in-salesforce-and-heroku-data-services-569e"&gt;Data Modeling in Salesforce and Heroku Data Services&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/jasonomnivo/building-front-end-app-experiences-with-clicks-not-code-2m6e"&gt;Building Front-End App Experiences with Clicks, Not Code&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/jasonomnivo/custom-app-experiences-with-lightning-web-components-4i39"&gt;Custom App Experiences with Lightning Web Components&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/jasonomnivo/lightning-web-components-events-and-lightning-message-service-21b8"&gt;Lightning Web Components, Events and Lightning Message Service&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/jasonomnivo/automating-business-processes-using-salesforce-flows-and-apex-923"&gt;Automating Business Processes Using Salesforce Flows and APEX&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/jasonomnivo/scale-salesforce-apps-using-microservices-on-heroku-43k7"&gt;Scale Salesforce Apps Using Microservices on Heroku&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/jasonomnivo/more-scaling-salesforce-apps-using-heroku-microservices-3k1f"&gt;More Scaling Salesforce Apps Using Heroku Microservices&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Just as a quick reminder: I’ve been following this Trailhead Live video series to brush up and stay current on the latest app development trends on these platforms that are key for my career and business. I’ll be sharing each step for building the app, what I’ve learned, and my thoughts from each session. These series reviews are both for my own edification as well as for others who might benefit from this content.&lt;/p&gt;

&lt;p&gt;The Trailhead Live sessions and schedule can be found here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://trailhead.salesforce.com/live" rel="noopener noreferrer"&gt;https://trailhead.salesforce.com/live&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Trailhead Live sessions I’m writing about can also be found at the links below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://trailhead.salesforce.com/live/videos/a2r3k000001n2Jj/modern-app-development-on-salesforce" rel="noopener noreferrer"&gt;https://trailhead.salesforce.com/live/videos/a2r3k000001n2Jj/modern-app-development-on-salesforce&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/playlist?list=PLgIMQe2PKPSK7myo5smEv2ZtHbnn7HyHI" rel="noopener noreferrer"&gt;https://www.youtube.com/playlist?list=PLgIMQe2PKPSK7myo5smEv2ZtHbnn7HyHI&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Last Time…
&lt;/h1&gt;

&lt;p&gt;Last time we dove deeper into connecting services and apps hosted on Heroku with Salesforce to provide real-time notifications and IoT data to Salesforce as well as how to scale these services for massive throughput needs.  This time we’re looking at automated ways to verify that our Javascript apps and services code are running correctly.  Specifically, we are going to learn about Javascript Unit Testing.&lt;/p&gt;

&lt;p&gt;Automated unit testing is an important part of the application development process and a key component to making sure that code is running and behaving as expected.  Unlike with Salesforce APEX code, which requires at least 75% overall code coverage of triggers and classes, Javascript apps don’t explicitly require unit tests, but it is simply good development practice to have unit tests as part of the process.  Applications that try to cut corners on this aspect of the application development lifestyle end up paying the price in the form of discovering more expensive bugs during regression testing or worse, shipping apps with bugs to customers and end-users.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Primer on Unit Testing
&lt;/h2&gt;

&lt;p&gt;What is “unit testing” exactly and what’s different about unit testing versus another testing methodology like regression testing or smoke testing?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  The “unit” part refers to verifying that a discrete method in the code, functionality, or automation is working as intended separately from other dependencies.  So, in Javascript, if you have a particular function that is supposed to take some arguments, process them, then fire a callback, you might write unit tests that target that specific function as opposed to testing the entire class.&lt;/li&gt;
&lt;li&gt;  The “testing” part simply refers to ensuring the method in code, functionality or automation is working as expected.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnqtqbh3sgoor0cb0y98o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnqtqbh3sgoor0cb0y98o.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Unit tests in a nutshell&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Here are some examples of how unit tests can be valuable:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Identify bugs easily and earlier&lt;/li&gt;
&lt;li&gt;  Reduce costs related to fixing bugs and QA efforts&lt;/li&gt;
&lt;li&gt;  Facilitate code design and refactoring&lt;/li&gt;
&lt;li&gt;  Self-documents sets of test cases&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;However, these benefits are only fully realized after implementing unit testing thoughtfully and correctly.  This process is often implemented poorly or skipped entirely.&lt;/p&gt;
&lt;h2&gt;
  
  
  A Framework for Unit Testing
&lt;/h2&gt;

&lt;p&gt;Regardless of the programming language, we’re using, a good framework to base our unit test design is the Arrange, Act, and Assert (AAA) framework.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzo9jts11z9r1kwwbbkr2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzo9jts11z9r1kwwbbkr2.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A good thing to remember with unit testing is that you are managing the “expectations” or “specifications” of the code with unit tests.  This means the unit tests have something to say about code specs and what the expectations are for the code when it runs.  In some cases, I’ve heard of development methods that involve writing the unit tests _first, _and then developing the actual code later since the unit tests can act as documentation for how the code should behave.&lt;/p&gt;

&lt;p&gt;Some Javascript examples for can include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Arrange&lt;/strong&gt;: Test data setup and inserting the necessary objects/records for the unit test&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Act&lt;/strong&gt;: Call your methods/functions or otherwise run the code you want to test and capture the result&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Assert&lt;/strong&gt;: Create assertion statements in your unit test and compare the results you captured with expected results.  You want the test to error out or notify you in some way if the result you captured deviates from the expected result.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Jest – Testing Tool for Javascript and LWC
&lt;/h2&gt;

&lt;p&gt;Javascript has a number of different testing libraries and frameworks available, but we’re focusing on one in particular: Jest.  This is the recommended testing framework for Salesforce Lightning Web Components (LWC) because of its ease-of-use, open-source nature, and popularity.  Specifically for LWC, Salesforce has a wrapper library on top of Jest called “sfdc-lwc-jest” which can be found at the following Github repo.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/salesforce/sfdx-lwc-jest" rel="noopener noreferrer"&gt;https://github.com/salesforce/sfdx-lwc-jest&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Also if you’re using Visual Studio Code (VS Code) with LWC (and you should), you will also want to install the following extension packs for VS Code.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;a href="https://developer.salesforce.com/tools/sfdxcli" rel="noopener noreferrer"&gt;Salesforce CLI&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://marketplace.visualstudio.com/items?itemName=salesforce.salesforcedx-vscode" rel="noopener noreferrer"&gt;VSCode Extension Pack for Salesforce&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://github.com/jest-community/vscode-jest" rel="noopener noreferrer"&gt;vscode-jest extension from jest-community&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Unit Testing for the eCars App
&lt;/h2&gt;

&lt;p&gt;The Javascript LWC apps and microservices hosted on the Heroku side of our app have a decent number of client-side interactions through the UI.  Specifically, we are going to test the Car Configurator app.  It makes sense to apply unit testing to our app so that when we make enhancements and additions to the code, our unit tests can help us catch issues with the app.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8d8i56l3o2zhcn3i8wz1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8d8i56l3o2zhcn3i8wz1.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;So many buttons and interactions, so many ways errors can happen&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The Javascript car configurator app we are going to test can be found on the&lt;a href="https://github.com/trailheadapps/ecars/tree/main/force-app/main/default/lwc/carConfigurator" rel="noopener noreferrer"&gt; eCars app Github repository&lt;/a&gt;.  If you’ve been following along with this series, then you should have already done some previous setup work installing the repo in VS Code and deploying it to a Salesforce scratch org.&lt;/p&gt;

&lt;p&gt;If you look at the .html and .js file in the carConfigurator LWC, you’ll see that the HTML has some expected behavior and bindings to variables in the .js file.  For our tests, we’re going to test that the LWC renders the expected components and values to the DOM as the test progresses.  We’ll soon look at how Jest and the sfdc-lwc-jest wrapper library makes this magic happen.&lt;/p&gt;

&lt;p&gt;First, we will need to create a testing scaffold for our unit tests with the following command in VS Code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sfdx force:lightning:lwc:test:create -f [file path]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the command runs successfully, your terminal should look something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzrlx690txg5jmjocyets.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzrlx690txg5jmjocyets.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This creates a carConfigurator.test.js test scaffold file that we can use to build our tests.   There should be a pre-built stub for the functions in the test file that you would expand upon as you build out your tests.&lt;/p&gt;

&lt;p&gt;When you initialize your LWC project in VS Code and take a look at the package.json file, you’ll see that there are some lwc-dependencies and scripts that are included in the package.  These scripts help make some of the lwc-jest magic happen.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbyed1e1y7qekizenhzip.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbyed1e1y7qekizenhzip.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Some lwc-jest dependencies called out in the package.json file&lt;/p&gt;

&lt;h2&gt;
  
  
  Unit Tests Code in Detail
&lt;/h2&gt;

&lt;p&gt;There’s a lot to unpack if you’re like me and have never done Javascript unit testing or worked with the Jest library before.  So, we will skip ahead to the fully built-out solution that is used in the demo and pick out some important things to note.  Here’s the fully completed carConfigurator.test.js code below.  In each of the test methods, you can get an idea of what the unit tests are testing for by looking at the name/description right after the &lt;code&gt;it()&lt;/code&gt; function declaration.  We’ll review some of the important highlights in this test script after you’ve scrolled through.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { createElement } from "lwc";
import CarConfigurator from "c/carConfigurator";
import CURRENCY from "@salesforce/i18n/currency";
import invokePdfCreateService from "@salesforce/apex/PdfCreateService.invokePdfCreateService";

jest.mock(
  "@salesforce/apex/PdfCreateService.invokePdfCreateService",
  () =&amp;gt; {
return {
      default: jest.fn(),
};
  },
  { virtual: true }
);

describe("c-car-configurator", () =&amp;gt; {
  afterEach(() =&amp;gt; {
while (document.body.firstChild) {
      document.body.removeChild(document.body.firstChild);
}
  });

  // Helper function to wait until the microtask queue is empty. This is needed for promise
  // timing when calling imperative Apex.
  function flushPromises() {
// eslint-disable-next-line no-undef
return new Promise((resolve) =&amp;gt; setImmediate(resolve));
  }

  it("renders section 1 with image", () =&amp;gt; {
const element = createElement("c-car-configurator", {
  is: CarConfigurator,
});
    document.body.appendChild(element);
const imageDiv = element.shadowRoot.querySelector("img");
const rangeAnchors = element.shadowRoot.querySelectorAll("a");
const formattedNumbers = element.shadowRoot.querySelectorAll(
      "lightning-formatted-number"
);
return Promise.resolve().then(() =&amp;gt; {
      expect(imageDiv).not.toBeNull();
      expect(imageDiv.src).toBe(
        "https://sfdc-demo.s3-us-west-1.amazonaws.com/ecars/car_white.jpg"
  );
  expect(rangeAnchors.length).toBe(3);
      expect(rangeAnchors[0].dataset.range).toBe("Short Range");
      expect(rangeAnchors[1].dataset.range).toBe("Medium Range");
      expect(rangeAnchors[2].dataset.range).toBe("Long Range");
  expect(formattedNumbers.length).toBe(3);
      expect(formattedNumbers[0].currencyCode).toBe(CURRENCY);
      expect(formattedNumbers[0].value).toBe(25000);
      expect(formattedNumbers[1].value).toBe(35000);
      expect(formattedNumbers[2].value).toBe(45000);
});
  });

  it("navigates to different section on next button click", () =&amp;gt; {
const element = createElement("c-car-configurator", {
  is: CarConfigurator,
});
    document.body.appendChild(element);
const button = element.shadowRoot.querySelector("lightning-button");
    button.click();
return Promise.resolve().then(() =&amp;gt; {
  const exteriorColorAnchors = element.shadowRoot.querySelectorAll("a");
      expect(exteriorColorAnchors.length).toBe(5);
  expect(exteriorColorAnchors[0].dataset.color).toBe("white");
      expect(exteriorColorAnchors[1].dataset.color).toBe("black");
      expect(exteriorColorAnchors[2].dataset.color).toBe("red");
      expect(exteriorColorAnchors[3].dataset.color).toBe("blue");
      expect(exteriorColorAnchors[4].dataset.color).toBe("green");
});
  });

  it("invokes pdf processing service", () =&amp;gt; {
    invokePdfCreateService.mockResolvedValue(true);
const LEADID = "00Q9A000001TNllUAG";
const INPUT_PARAMETERS = {
  price: 25000,
  range: "Short Range",
      exteriorColor: "Pearl White",
      interiorColor: "Vegan White",
      leadRecordId: LEADID,
};

const element = createElement("c-car-configurator", {
  is: CarConfigurator,
});
document.body.appendChild(element);
const button = element.shadowRoot.querySelector("lightning-button");
    button.click();
const section2NextButton = element.shadowRoot.querySelector(".button-next");
    section2NextButton.click();
const section3NextButton = element.shadowRoot.querySelector(".button-next");
    section3NextButton.click();
return flushPromises().then(() =&amp;gt; {
  const recordEditFormElement = element.shadowRoot.querySelector(
        "lightning-record-edit-form"
  );
      expect(recordEditFormElement).not.toBeNull();
  const inputFieldElement = element.shadowRoot.querySelector(
        "lightning-input-field"
  );
      inputFieldElement.value = LEADID;
      expect(inputFieldElement).not.toBeNull();
      inputFieldElement.dispatchEvent(new CustomEvent("change"));
  const section4NextButton = element.shadowRoot.querySelector(
        ".button-next"
  );
      section4NextButton.click();
      expect(invokePdfCreateService.mock.calls.length).toBe(1);
      expect(invokePdfCreateService.mock.calls[0][0]).toEqual({
        input: INPUT_PARAMETERS,
  });
});
  });
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Import declarations&lt;/strong&gt; are importing some of the required dependencies for running our tests.  Note that you can’t use the createElement in LWC code, but you can for the unit test file.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Jest.mock&lt;/strong&gt; is an interface that reminds me of the HTTPCalloutMock interface from Salesforce unit testing.  Jest.mock mocks calls and responses to external services. In the context of our test, we can’t _actually _make an imperative call to our PdfCreateService APEX class/methods so we have to mock this call and response. &lt;/p&gt;

&lt;p&gt;It’s important to note that this could be a point of failure in our tests because what we mock up could be different than how the actual PdfCreateService method behaves.  Therefore, it’s a good idea to have a unit test on the Salesforce side that verifies that the PdfCreateService class is behaving correctly.  This is actually exactly what we will do in the next session.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A DOM reset&lt;/strong&gt; is needed after each unit test because the same jsdom instance is shared across all unit tests in the file.  The code snippet below ensures that we’re working with a clean slate after each unit test so that we’re not getting erroneous test results due to leftovers in the jsdom after the previous unit test.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;describe("c-car-configurator", () =&amp;gt; {
  afterEach(() =&amp;gt; {
while (document.body.firstChild) {
      document.body.removeChild(document.body.firstChild);
}
  });
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The flushPromises&lt;/strong&gt; code snippet below helps us handle callbacks and making sure that each callback resolves properly with a Promise.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  function flushPromises() {
// eslint-disable-next-line no-undef
return new Promise((resolve) =&amp;gt; setImmediate(resolve));
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;The unit tests themselves now make up the remainder of the test file.  There is a lot of material to unpack in each specific unit test in terms of how to set- p the test and invoke what needs to be tested, so we’ll have some homework to do at the end of this article.  However, each individual unit test will have a general form that follows something like the code below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  it("A friendly label for your unit test", () =&amp;gt; {
//Initialize your test case here
const element = createElement("c-component-name", {
  is: ComponentName,
});
document.body.appendChild(element);
//Then perform the actions that your test is seeking to test/simulate
const button = element.shadowRoot.querySelector("button-being-tested");
button.click();

//Resolve Promises
return Promise.resolve().then(() =&amp;gt; {
  //Set a variable for the element you're inspecting
  const ElementToBeTested = element.shadowRoot.querySelectorAll("selectorForElementToBeTested");

//Make assertions with the expect() function and check if you're getting the correct desired result
Const ExpectedValue = "Expected value";
  expect(ElementToBeTested.property).toBe(ExpectedValue);
});
  });
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, even though the specific code in each unit test varies, all tests follow the same pattern from our original AAA Framework.  With this framework, pretty much any element in our app, including rendering behavior, navigation, button clicks, and service callouts can be unit tested to ensure that the code is working correctly!&lt;/p&gt;

&lt;h1&gt;
  
  
  Concluding Thoughts
&lt;/h1&gt;

&lt;p&gt;I’m going, to be honest.  From someone who came from a background of unit testing for Salesforce APEX code, the topics covered here were pretty foreign to me.  I think the hardest part to grasp was the Jest methods used for testing UI behavior and rendering items.  For example, “shadow DOM”, “root and child elements”, and other front-end heavy items were not things I typically worried about as a Salesforce administrator or developer.&lt;/p&gt;

&lt;p&gt;However, I also recall a time when APEX unit testing was also a pretty foreign concept to me. But once I understood the purpose of unit testing and the syntax and methods used to set up and run the tests and create assert statements to verify that the code is running properly, things became much easier.  I expect the same outcome with Javascript unit testing and learning how to use tools like Jest.&lt;/p&gt;

&lt;p&gt;For more information and advanced topics related to Javascript and LWC unit testing, check out the links to the resources below:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;a href="https://trailhead.salesforce.com/content/learn/modules/test-lightning-web-components" rel="noopener noreferrer"&gt;Testing Lightning Web Components Trailhead Module&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://jestjs.io/docs/en/jest-object" rel="noopener noreferrer"&gt;Jest Objects&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://jestjs.io/docs/en/mock-functions" rel="noopener noreferrer"&gt;Jest Mock Functions&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://jestjs.io/docs/en/using-matchers" rel="noopener noreferrer"&gt;Jest Matchers&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://jestjs.io/docs/en/configuration" rel="noopener noreferrer"&gt;Jest Configuration&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://github.com/salesforce/sfdx-lwc-jest/tree/master/src/lightning-stubs" rel="noopener noreferrer"&gt;sfdc-lwc-jest library&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://developer.salesforce.com/docs/component-library/documentation/en/lwc/lwc.testing" rel="noopener noreferrer"&gt;Test Lightning Web Components&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://github.com/trailheadapps/lwc-recipes" rel="noopener noreferrer"&gt;LWC Recipes&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://github.com/trailheadapps/lwc-recipes-oss" rel="noopener noreferrer"&gt;LWC Recipes OSS&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the next article, we will explore more unit testing but specifically for Salesforce and APEX code.&lt;/p&gt;

&lt;p&gt;If you haven’t already joined the official Chatter group for this series, I certainly recommend you do so. You will get the full value of the experience, ask questions, and start discussions with the group. Oftentimes, there are valuable discussions and additional references available, such as presentation slides and links to other resources and references.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://sforce.co/34Ld7xz" rel="noopener noreferrer"&gt;https://sforce.co/34Ld7xz&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;About me:  I’m an 11x certified Salesforce professional who’s been running my own Salesforce consultancy for several years. If you’re curious about my backstory on accidentally turning into a developer and even competing on stage on a quiz show at one of the Salesforce conventions, you can read&lt;a href="http://green.salesforce.com/blog/2017/04/accidental-developer-to-dst17-finalist.html" rel="noopener noreferrer"&gt; this article&lt;/a&gt; I wrote for the Salesforce blog a few years ago.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>heroku</category>
      <category>testing</category>
    </item>
    <item>
      <title>More Scaling Salesforce Apps Using Heroku Microservices</title>
      <dc:creator>Jason Sun</dc:creator>
      <pubDate>Thu, 04 Feb 2021 19:13:00 +0000</pubDate>
      <link>https://dev.to/jasonomnivo/more-scaling-salesforce-apps-using-heroku-microservices-3k1f</link>
      <guid>https://dev.to/jasonomnivo/more-scaling-salesforce-apps-using-heroku-microservices-3k1f</guid>
      <description>&lt;h2&gt;
  
  
  &lt;strong&gt;(Heroku and Salesforce - From Idea to App, Part 9)&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;This is the ninth article documenting what I’ve learned from a series of&lt;a href="https://trailhead.salesforce.com/live/videos/a2r3k000001n2Ig/modern-app-development-on-salesforce/?ref=hackernoon.com" rel="noopener noreferrer"&gt; 13 Trailhead Live video sessions on Modern App Development on Salesforce and Heroku&lt;/a&gt;.  In these articles, we’re focusing on how to combine Salesforce with&lt;a href="https://www.heroku.com/" rel="noopener noreferrer"&gt; Heroku&lt;/a&gt; to build an “eCars” app—a sales and service application for a fictitious electric car company (“Pulsar”).  eCars allows users to customize and buy cars, service techs to view live diagnostic info from the car, and more. In case you missed my previous articles, you can find the links to them below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/jasonomnivo/modern-app-development-on-salesforce-and-heroku-206j"&gt;Modern App Development on Salesforce and Heroku&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/jasonomnivo/jumping-into-heroku-development-48ep"&gt;Jumping into Heroku Development&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/jasonomnivo/data-modeling-in-salesforce-and-heroku-data-services-569e"&gt;Data Modeling in Salesforce and Heroku Data Services&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/jasonomnivo/building-front-end-app-experiences-with-clicks-not-code-2m6e"&gt;Building Front-End App Experiences with Clicks, Not Code&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/jasonomnivo/custom-app-experiences-with-lightning-web-components-4i39"&gt;Custom App Experiences with Lightning Web Components&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/jasonomnivo/lightning-web-components-events-and-lightning-message-service-21b8"&gt;Lightning Web Components, Events and Lightning Message Service&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/jasonomnivo/automating-business-processes-using-salesforce-flows-and-apex-923"&gt;Automating Business Processes Using Salesforce Flows and APEX&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/jasonomnivo/scale-salesforce-apps-using-microservices-on-heroku-43k7"&gt;Scale Salesforce Apps Using Microservices on Heroku&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Just as a quick reminder:  I’ve been following this Trailhead Live video series to brush up and stay current on the latest app development trends on these platforms that are key for my career and business.  I’ll be sharing each step for building the app, what I’ve learned, and my thoughts from each session.  These series reviews are both for my own edification as well as for others who might benefit from this content.&lt;/p&gt;

&lt;p&gt;The Trailhead Live sessions and schedule can be found here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://trailhead.salesforce.com/live" rel="noopener noreferrer"&gt;https://trailhead.salesforce.com/live&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Trailhead Live sessions I’m writing about can also be found at the links below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://trailhead.salesforce.com/live/videos/a2r3k000001n2Jj/modern-app-development-on-salesforce" rel="noopener noreferrer"&gt;https://trailhead.salesforce.com/live/videos/a2r3k000001n2Jj/modern-app-development-on-salesforce&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/playlist?list=PLgIMQe2PKPSK7myo5smEv2ZtHbnn7HyHI" rel="noopener noreferrer"&gt;https://www.youtube.com/playlist?list=PLgIMQe2PKPSK7myo5smEv2ZtHbnn7HyHI&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Last Time…&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Last time we explored connecting microservices hosted on Heroku with Salesforce to offload high-cost operations and processes.  It turns out this topic is important enough to warrant a second video and article dedicated to the same subject! &lt;/p&gt;

&lt;p&gt;This time we are going to cover some pretty cool Heroku features and integrations with Heroku apps including Progressive Web Apps (PWAs), using Kafka to scale MQTT protocols, and capturing change events in near real time.&lt;/p&gt;

&lt;p&gt;In the very first video and article of the series, there were some previews of these potential use cases for these Heroku platform features, but now we’re going to see actual examples of their use and implementation!&lt;/p&gt;

&lt;p&gt;As a reminder, the GitHub repo for this series and the eCars application used throughout is available at the following URL.  There are a number of other sample apps in the overall repo as well.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/trailheadapps/ecars" rel="noopener noreferrer"&gt;https://github.com/trailheadapps/ecars&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Architecture of the eCars Application&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;So far, the two major parts or “clouds'' of the application have been focused on Sales Cloud and Leads configuring their potential cars and now Service Cloud as well for certain customer service use cases.  Both of the Salesforce clouds have external integrations.  On the Sales Cloud side, we have a Progressive Web App (PWA) for the car configurator, a Heroku microservice for the handling of PDF generation, and a component for push notifications.  On the Service Cloud side, we will have a streaming data Heroku app that leverages MQTT, Internet-of-Things (IoT), and Apache Kafka while integrating with Salesforce via web service APIs.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fwfhrks18i1uyei86o8r9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fwfhrks18i1uyei86o8r9.png" alt="eCars Application Architecture"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;eCars Application Architecture&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In this session we look at three demos, use cases, or integrations with Heroku apps and microservices:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A PWA car configurator that sends leads to Salesforce, manages push notifications, and crosses boundaries of native and web applications.&lt;/li&gt;
&lt;li&gt;A real-time Heroku streaming data app that automatically opens a case and provides real-time IoT data from the car’s sensors that are reporting issues&lt;/li&gt;
&lt;li&gt;Synchronizing data with Salesforce and an external data store for change data capture&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Subscription and Push Notifications PWA Demo&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;First let’s look at the Heroku PWA that’s handling the car configurator and doing two things:  Pushing a new lead to Salesforce Sales Cloud and subscribing that lead to notifications using the contact information they provide.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fr6f8con1fgysshu3xbsn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fr6f8con1fgysshu3xbsn.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;An example lead completing their car configuration and providing contact info&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Once the user completes the information on this page, a lead is sent to Salesforce via the Salesforce REST API and the JSForce javascript library, which provides an abstraction layer for the Heroku app to make API calls to Salesforce.&lt;/p&gt;

&lt;p&gt;Once the lead is in Salesforce, we can see that it’s possible for the salesperson to manually send out a web push notification back to the web application to the prospective buyer. This could also be invoked automatically using Salesforce’s automation tools such as Flows.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fwee2gychkhzwv7tjft16.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fwee2gychkhzwv7tjft16.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Sending the notification from Salesforce results in the web notification in the top right corner&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In this architecture, we effectively have real-time notifications between Salesforce and the prospective user’s machine.  This is possible with something called a “Service Worker” which is a kind of Javascript application that runs completely in the browser so that notifications can be received even when the web page isn’t open.  I bet this is partially why my internet browser is so RAM-hungry?&lt;/p&gt;

&lt;p&gt;Another very cool feature of PWAs is that they are not just web apps but can be installed and run from the desktop iOS or a mobile device and run like a native app providing the same experience, independent of the platform they run on!  This is great because the PWA frees you from having to maintain separate codebases for your web app and your native mobile and desktop apps.&lt;/p&gt;

&lt;p&gt;Finally, the PWA we see in the demo is actually built using Lightning Web Components so this wasn’t actually some specialized node.js app that’s far removed from the Salesforce ecosystem.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Under the Hood of the eCars PWA&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ft64leejbr4zcxhjyze1n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ft64leejbr4zcxhjyze1n.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Customer-facing PWA app architecture&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Taking a look under the hood of the PWA App, there are a few components to explore.  In the graphic above, we have in the boxes from left to right: the client’s browser, the Heroku server, and the Salesforce instance on the far right side.&lt;/p&gt;

&lt;p&gt;Without diving too far into the weeds of the actual code (which you can just explore in the Github repo), here are some notable highlights:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  The Heroku server is providing an HTTPS server via express to serve up the PWA app pages.&lt;/li&gt;
&lt;li&gt;  The Service Worker lives completely on the client’s browser to manage subscribes, push notifications, and communications with the HTTPS server.&lt;/li&gt;
&lt;li&gt;  The web-push library facilitates communication with the Service Worker and Salesforce APEX classes with web services callouts.&lt;/li&gt;
&lt;li&gt;  The service worker, running totally on a separate thread on the client’s browser provides some offline capabilities as well as pre- and run-time caching and background synchronization.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I have found that the &lt;a href="https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/using_resources_composite_graph.htm" rel="noopener noreferrer"&gt;Composite Graph API&lt;/a&gt; is potentially very useful on the Salesforce side.  Typically when making inbound calls to create multiple related records via the Salesforce API, you have to make multiple API calls—one call to create the parent, another call to create child objects, and so on.) Then, you need to manage cases that involve rolling back the entire transaction thread because maybe the parent insert was successful but then only some of the child records inserted successfully while the rest errored-out.  With the Graph API, you can make a single callout to string together otherwise separate calls and manage the success/failure of the entire composite call as one.  This should really be the gold standard when it comes to operations that insert multiple records!&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Real-Time IoT eCars Data Demo&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;In the next demo, we’re looking at a scenario that involves getting IoT data from the cars’ sensors and pipe the information to our app in real time. This will enable us to take some preemptive action on certain triggering events (a rapidly-draining battery in this case) and empower the service agents with that data.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F4bx8e71y4mpriilswjci.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F4bx8e71y4mpriilswjci.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;An automatically opened case due to battery anomaly with real-time data accessible in the case view&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;So, we’re looking at a Salesforce service cloud case that was automatically opened because the IoT data received by our application from a particular car was not performing within expected thresholds.  Then, in two of the tabs on the case, we can see lightning components that have battery diagnostic and real-time data streaming to the case for the service agents to access. &lt;/p&gt;

&lt;p&gt;Imagine that we then combine this with Salesforce automation to send the owner of the vehicle a preemptive email notifying them that Pulsar is aware of the issue and are looking into it.  We can also combine this with what we did in the PWA and send a push notification with the same content!  This would take customer service and the experience of the Pulsar brand to a whole new level.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Under the Hood of Real-Time IoT eCars Data&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;So how do we get all this rich IoT data from the cars all the way back to Salesforce?  Let’s take a look under the hood (pun intended) and see what kinds of components are making this magic happen.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F6zkozqsjd855ieicosbc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F6zkozqsjd855ieicosbc.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Real-time service on Heroku&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Here are some components to highlight below (Remember that all the code running behind these components can be found in eCars app Github repo)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;MQTT Broker –&lt;/strong&gt; This MQTT broker is a standalone application running on its own Heroku Dyno.  MQTT is an extremely lightweight messaging protocol for IoT use cases.  It’s a simple publish/subscribe messaging transport that is ideal for connecting remote devices with very little code and minimal network bandwidth.  This MQTT broker is receiving data from the cars’ sensors and publishing them to clients that subscribe to the data.  The specific MQTT library used for the eCars app is called Aedes and is a barebones MQTT server.  More information is available on Aedes in the links at the end of the article.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;eCars Real Time –&lt;/strong&gt; The eCars real-time application is another standalone application running on its own dyno.  As you can see, it comprises an &lt;strong&gt;events persistence module&lt;/strong&gt; and an &lt;strong&gt;events connector module&lt;/strong&gt;.  The events persistence module handles taking the data from the MQTT Broker and persisting it to a sensor data database where it can be stored permanently and queried like a normal SQL database and perhaps stored in a data warehouse later.  The events connector module also subscribes to the same MQTT Broker but has a different job—communicating with the Salesforce liveData LWC via a Raw Websockets API.  This allows the service user on the Salesforce side to access the sensor data in real time.&lt;/p&gt;

&lt;p&gt;Of course, the amount of data throughput can get pretty crazy as Pulsar sells cars and more of them are on the road all broadcasting sensor data.  In order to scale this application, Apache Kafka comes into play.  Apache Kafka is a distributed commit log for rapid, fault-resistant communication between producers and consumers using message-based topics and provides the backbone for building distributed applications capable of handling billions of events and millions of transactions.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fr0kshufn354zsjn4y3xs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fr0kshufn354zsjn4y3xs.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Apache Kafka for when you need to handle massive throughput&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;With Apache Kafka added on, it helps the app increase real-time data throughput and allows other microservices to consume/subscribe to data without producing additional overhead.  It’s not necessary to have Apache Kafka on your Heroku instance for the eCars app to function as it’s only needed for massive scaling use cases in production.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Data Synchronization with Change Data Capture&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The final use case example is related to data synchronization and change data capture.  This is similar to the previous “publish/subscribe” framework of the IoT example but can be applied to any use case where you might want to synchronize data between disparate applications or data stores.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fffir0eeb9zyoce5bln0u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fffir0eeb9zyoce5bln0u.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Data synchronization with change data capture&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The&lt;/em&gt; “event bus” is key to this architecture.  It is where change data events are published to and can be subscribed from.  This event bus is playing the same role as the MQTT Broker in the previous example.  In our model above, the event is a vehicle changing status to “sold.”  This update is committed to the database but also published to the event bus.  This event bus can then serve up the change events to multiple subscribers. &lt;/p&gt;

&lt;p&gt;In our eCars app, there is an LWC using the emp-API base component that subscribes to the events, however, a subscriber can also sit outside of the application and subscribe to the same event bus to then sync the data to an external database. &lt;/p&gt;

&lt;p&gt;The main advantage of this model is that point-to-point integrations between multiple systems to keep the data in sync are no longer required.  The event bus can serve as the singular hub for distributing this information.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Concluding Thoughts&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The content in the demos covered for the eCars app is pretty advanced in terms of the level of sophistication and integration from the perspective of typical Salesforce implementations.  Using a PWA or scaling massively using Apache Kafka may not be common, however, the purpose of this content is to expand everyone’s idea of the realm of possibilities that exist in the Salesforce ecosystem. &lt;/p&gt;

&lt;p&gt;As a Salesforce administrator or developer, I find that it’s somewhat easy to get a bit of tunnel vision and somewhat “stuck” in our thinking in terms of possibilities when architecting an application in the ecosystem. Therefore, I find it refreshing to look at examples that really push the edges of what is possible to build.&lt;/p&gt;

&lt;p&gt;For more information, trailhead modules, and advanced topics related to scaling Salesforce apps with Heroku and event-driven architecture, check out the links to the resources below:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;a href="https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/using_resources_composite_graph.htm" rel="noopener noreferrer"&gt;Composite Graph APIs&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://trailhead.salesforce.com/en/content/learn/modules/change-data-capture" rel="noopener noreferrer"&gt;Change Data Capture Basics&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://developer.salesforce.com/blogs/2020/12/build-connected-apps-anywhere-using-lightning-base-components.html" rel="noopener noreferrer"&gt;Build Connected Apps with LWC Base Components NPM&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://web.dev/progressive-web-apps/" rel="noopener noreferrer"&gt;Deep Dive Into Progressive Web Apps&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://developers.google.com/web/tools/workbox" rel="noopener noreferrer"&gt;Explore WorkBox for PWA&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://mqtt.org/" rel="noopener noreferrer"&gt;MQTT: The Standard IoT Messaging&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://www.npmjs.com/package/aedes" rel="noopener noreferrer"&gt;aedes: Barebone MQTT server&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://www.npmjs.com/package/sinek" rel="noopener noreferrer"&gt;sinek: High Level Kafka Client&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://www.heroku.com/kafka" rel="noopener noreferrer"&gt;Apache Kafka on Heroku&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API" rel="noopener noreferrer"&gt;The WebSocket API&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the next article, we’ll walk through unit testing methods and tools for Javascript applications.&lt;/p&gt;

&lt;p&gt;If you haven’t already joined the official Chatter group for this series, I certainly recommend doing so.  This will give you the full value of the experience and also pose questions and start discussions with the group.  There are often valuable discussions and additional references available, such as presentation slides and other resources and references.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://sforce.co/34Ld7xz" rel="noopener noreferrer"&gt;https://sforce.co/34Ld7xz&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;About me:  I’m an 11x certified Salesforce professional who’s been running my own Salesforce consultancy for several years. If you’re curious about my backstory on accidentally turning into a developer and even competing on stage on a quiz show at one of the Salesforce conventions, you can read&lt;a href="http://green.salesforce.com/blog/2017/04/accidental-developer-to-dst17-finalist.html" rel="noopener noreferrer"&gt; this article&lt;/a&gt; I wrote for the Salesforce blog a few years ago.&lt;/p&gt;

</description>
      <category>heroku</category>
      <category>salesforce</category>
    </item>
    <item>
      <title>Scale Salesforce Apps Using Microservices on Heroku</title>
      <dc:creator>Jason Sun</dc:creator>
      <pubDate>Sat, 30 Jan 2021 04:10:49 +0000</pubDate>
      <link>https://dev.to/jasonomnivo/scale-salesforce-apps-using-microservices-on-heroku-43k7</link>
      <guid>https://dev.to/jasonomnivo/scale-salesforce-apps-using-microservices-on-heroku-43k7</guid>
      <description>&lt;h2&gt;
  
  
  &lt;strong&gt;(Heroku and Salesforce - From Idea to App, Part 8)&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;This is the eighth article documenting what I’ve learned from a series of&lt;a href="https://trailhead.salesforce.com/live/videos/a2r3k000001n2Ig/modern-app-development-on-salesforce/?ref=hackernoon.com" rel="noopener noreferrer"&gt; 13 Trailhead Live video sessions on Modern App Development on Salesforce and Heroku&lt;/a&gt;. In these articles, we’re focusing on how to combine Salesforce with&lt;a href="https://www.heroku.com/" rel="noopener noreferrer"&gt; Heroku&lt;/a&gt; to build an “eCars” app—a sales and service application for a fictitious electric car company (“Pulsar”) that allows users to customize and buy cars, service techs to view live diagnostic info from the car, and more. In case you missed my previous articles, you can find the links to them below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/jasonomnivo/modern-app-development-on-salesforce-and-heroku-206j"&gt;Modern App Development on Salesforce and Heroku&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/jasonomnivo/jumping-into-heroku-development-48ep"&gt;Jumping into Heroku Development&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/jasonomnivo/data-modeling-in-salesforce-and-heroku-data-services-569e"&gt;Data Modeling in Salesforce and Heroku Data Services&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/jasonomnivo/building-front-end-app-experiences-with-clicks-not-code-2m6e"&gt;Building Front-End App Experiences with Clicks, Not Code&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/jasonomnivo/custom-app-experiences-with-lightning-web-components-4i39"&gt;Custom App Experiences with Lightning Web Components&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/jasonomnivo/lightning-web-components-events-and-lightning-message-service-21b8"&gt;Lightning Web Components, Events and Lightning Message Service&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/jasonomnivo/automating-business-processes-using-salesforce-flows-and-apex-923"&gt;Automating Business Processes Using Salesforce Flows and APEX&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Just as a quick reminder: I’ve been following this Trailhead Live video series to brush up and stay current on the latest app development trends on these platforms that are key for my career and business. I’ll be sharing each step for building the app, what I’ve learned, and my thoughts from each session. These series reviews are both for my own edification as well as for others who might benefit from this content.&lt;/p&gt;

&lt;p&gt;The Trailhead Live sessions and schedule can be found here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://trailhead.salesforce.com/live" rel="noopener noreferrer"&gt;https://trailhead.salesforce.com/live&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Trailhead Live sessions I’m writing about can also be found at the links below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://trailhead.salesforce.com/live/videos/a2r3k000001n2Jj/modern-app-development-on-salesforce" rel="noopener noreferrer"&gt;https://trailhead.salesforce.com/live/videos/a2r3k000001n2Jj/modern-app-development-on-salesforce&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/playlist?list=PLgIMQe2PKPSK7myo5smEv2ZtHbnn7HyHI" rel="noopener noreferrer"&gt;https://www.youtube.com/playlist?list=PLgIMQe2PKPSK7myo5smEv2ZtHbnn7HyHI&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Last Time…&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Last time we explored ways to automate back-end processes on Salesforce using Flows and APEX and created several automations for our eCars app using Record-Triggered Flows and an APEX trigger. This time we are focusing entirely on how Heroku apps and microservices can help our Salesforce app scale for high-volume use cases.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Setting Up the App and Scratch Org via Github&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The eCars app Salesforce and Heroku code are available on Github at the following URL:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/trailheadapps/ecars" rel="noopener noreferrer"&gt;https://github.com/trailheadapps/ecars&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Go to the apps-&amp;gt;ecars-services directory for the specific Heroku services code for this session. The readme section in the directory contains useful information for deploying to Heroku.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fdb7tbiooj2di7m8wwe2k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fdb7tbiooj2di7m8wwe2k.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To get things set up we’ll need to deploy the Salesforce application to a Salesforce scratch org as well as the Heroku apps to the Heroku platform. If you are jumping into the middle of this series and have not yet set up your scratch org, it would be a good idea to go back to the first article in this series to review how to set up scratch orgs and your Salesforce dev hub as well as sign up for a free developer account on &lt;a href="https://www.heroku.com" rel="noopener noreferrer"&gt;Heroku&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To get a high-level idea of the architecture of the app, the following slide details how Sales Cloud and the Car Order Configurator will be interacting with the Heroku app and its microservices.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Faljqcopyaj8he1ihtp93.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Faljqcopyaj8he1ihtp93.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For deployment, we get two different methods on how to manage this (1) Automated and (2) Manual.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Flili08ev7k8djnodi5g3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Flili08ev7k8djnodi5g3.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To start, let’s review the steps for&lt;a href="https://github.com/trailheadapps/ecars#automated-deploy" rel="noopener noreferrer"&gt; Automated Deployment&lt;/a&gt; as also listed on the readme section in the Github repo. Julian has created a script (a Node.js program that will make this process easier) to get this up and running in the Salesforce and Heroku platforms. All of the installation pre-reqs, keys, and steps to configure your operating system before we move forward with deployment can be found&lt;a href="https://github.com/trailheadapps/ecars#installation" rel="noopener noreferrer"&gt; here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The automated deployment instructions reminds us of a few things: You must be authenticated in DevHub using the SF CLI and Heroku CLI, and you must have access to the repository in order to clone it:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fnveudq5353xxqpsi4zwo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fnveudq5353xxqpsi4zwo.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After cloning the repo and opening the project in VS Code, we can execute the eCars deployment script using the node binary + javascript file. This will show you a screen asking you various questions. It’s important that &lt;strong&gt;_developers read through all questions in detail _&lt;/strong&gt;because it will tell you the applications you are going to deploy. The script checks for git, node, SF CLI, and the Heroku CLI to ensure all the prerequisites are there. The script also requires you to answer a series of questions before continuing and then the deployment will take approximately 10 minutes to complete. This might be a step where specific system configurations or pre-requisites get missed and you may get error messages. If so, you can post on the&lt;a href="https://sforce.co/34Ld7xz" rel="noopener noreferrer"&gt; Chatter group discussion forum&lt;/a&gt; for this series to ask for help.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Flrv29k5mu9nrma8zypv6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Flrv29k5mu9nrma8zypv6.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fcxr8co7o2ev4kw2j8kue.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fcxr8co7o2ev4kw2j8kue.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The output of the script final steps of instructions&lt;/p&gt;

&lt;p&gt;The goal of this is to simplify the process for you as much as possible. The final items are “post-deployment steps” to perform after completing the automated deployment.   For extra credit, check out the&lt;a href="https://github.com/trailheadapps/ecars#manual-deploy" rel="noopener noreferrer"&gt; Manual Deployment&lt;/a&gt; for further understanding and learning (as well as a place to check out more detailed information should you run into errors during auto-deploy).&lt;/p&gt;

&lt;p&gt;In the JavaScript file, we have SF CLI commands, Heroku CLI commands, as well as Linux commands to perform automation. This is an example of a robust use case for devs on what you can do with a node script. Julian, the developer who authored the script, used the Shelljs package (you can check out this powerful library&lt;a href="https://www.npmjs.com/package/shelljs" rel="noopener noreferrer"&gt; here&lt;/a&gt; – note the weekly downloads!) because it provides the ability to write an automation that can run in both Windows and Unix platforms. It is an “implementation of Unix shell commands on top of the Node.js API” which you can review in more detail on the README&lt;a href="https://github.com/shelljs/shelljs" rel="noopener noreferrer"&gt; here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Deep Dive into the Node.js code and useful functions/scripts&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Those of you familiar with Node.js will know that you can use core modules as well as extend things easily with third-party modules. In this case, the Shelljs library provides the JavaScript object (JSON) that contains all of the required content to execute the external commands. Check out the screenshots below which show examples of exporting the commands from the index.js file and requiring them in our ecarsDeploy.js file.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F352d3cpu039h0tb2hug4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F352d3cpu039h0tb2hug4.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
Exporting the functions as JSON&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fphxim2m82y3e09j8guv3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fphxim2m82y3e09j8guv3.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
Requiring them in the ecarsDeploy.js file&lt;/p&gt;

&lt;p&gt;We continue to break down the modules and the code that starts the deployment process by function.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fxuiy4gc72zs312ae877r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fxuiy4gc72zs312ae877r.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ftocuk5pmmi3e2dnszjkz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ftocuk5pmmi3e2dnszjkz.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With javascript and Node.js, it’s important to get familiar with the well-known asynchronous functions that contain a command and then a callback function that runs when the external function or callback completes. Unlike strict-typed languages like APEX, things don’t execute in one thread so we have to manage cases where the external function/callback might run into a problem and never give us the callback. Since we don’t want to block execution and end up waiting forever for the callback, the standard in dealing with asynchronous operations like this is to use the async/await pattern. This relies on something called “Promises”, which all javascript developers should be familiar with. Promises allow you to execute async operations and guarantee they will return a value back without blocking the main execution thread.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fcmoz513hvvsgpkwhva17.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fcmoz513hvvsgpkwhva17.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
Example use of a Promise&lt;/p&gt;

&lt;p&gt;Another useful tool is the sed (“stream editor”) Linux command that allows you to replace strings in a file. Our app uses the sed command to access a template and substitute the correct URLs.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F04yj78xp65p7lviwgn2z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F04yj78xp65p7lviwgn2z.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ftta2301glctp40uvun2s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ftta2301glctp40uvun2s.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This command is extremely powerful because it gives you the ability to use the sed command to quickly modify metadata before pushing it into Salesforce.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The PDF Creation Microservice&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A common request for applications like the eCars app would be to generate a PDF document from data collected in the system. In this case, we are going to create a PDF of a car configuration that can then be printed by the sales user for the customer. Creating PDFs is actually a high-cost CPU operation, relatively speaking, so we are going to leverage a Heroku microservice to offload this from Salesforce to Heroku.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fr0v3ksz3raxx1mrvt44p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fr0v3ksz3raxx1mrvt44p.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Architecture and components between SF and Heroku for PDF generation process&lt;/p&gt;

&lt;p&gt;Here’s what we will expect to happen once this is implemented. A potential customer builds a car on the eCars app and submits a request for it. This creates a lead in Salesforce. In Salesforce, on the lead record, we can then access the Web Push Notification (another Heroku microservice) telling the lead their car is ready.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fpr4hhv836jwr8115896e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fpr4hhv836jwr8115896e.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now let’s say your lead is at the dealership and building a different version of the car. In the Car Configurator, a sales user can walk through the steps of model, color, and interior and can then attach the lead in Salesforce and generate a PDF with the car’s details.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fg9dgmk3eoj3j3xs1yg4q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fg9dgmk3eoj3j3xs1yg4q.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This PDF will be generated in Heroku and come over as an attachment on the files related list on the Lead record in Salesforce:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fjt9vyg6q8a5yv0wsbv0p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fjt9vyg6q8a5yv0wsbv0p.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So how do we do this? First, the configuration information data gets sent from Salesforce to the Heroku microservice. Heroku is using Node.js and a few libraries/modules to achieve this—specifically,&lt;a href="https://www.fastify.io/" rel="noopener noreferrer"&gt; Fastify&lt;/a&gt;,&lt;a href="https://www.npmjs.com/package/pdfmake" rel="noopener noreferrer"&gt; PDFmake&lt;/a&gt;, and&lt;a href="https://www.npmjs.com/package/jsforce" rel="noopener noreferrer"&gt; JSforce&lt;/a&gt;. One of the beauties of Heroku is the ability to combine all of these libraries to build powerful applications for a variety of use cases. Now some descriptions of each library:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Flpeqzhoxa7fkrlygsj0f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Flpeqzhoxa7fkrlygsj0f.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Diving first into Fastify, we are using &lt;strong&gt;Piscina&lt;/strong&gt; to help offset the load on the Heroku service as generating PDFs can be an intensive CPU operation. Piscina is a library to help manage something called the “workerThread” to generate the PDF and “downlog” the main thread of the application. This is implemented as a POST route, so we can have an APEX class in Salesforce that makes a callout to that endpoint via a POST method.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fizt3mvttyn1bv58ktufb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fizt3mvttyn1bv58ktufb.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then we have a &lt;code&gt;PDFGenerator&lt;/code&gt; class in the PDFMake library to be able to generate the PDF. This includes the &lt;code&gt;savePDFtoLead&lt;/code&gt; custom function that saves the PDF to the Salesforce lead.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F5qit9fr40cavqm0yjhz7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F5qit9fr40cavqm0yjhz7.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Finally, &lt;a href="https://jsforce.github.io/" rel="noopener noreferrer"&gt;jsForce&lt;/a&gt; is a javascript library that helps with interacting with the Salesforce REST API in javascript applications. In the jsForce code, there are functions to authenticate and create a connection to Salesforce as well as functions to send a SOQL query to Salesforce and get back and parse the results of that query.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F64ploh1eq8cr2zaqygot.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F64ploh1eq8cr2zaqygot.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To handle the PDF generated by the PDFMake library, we are receiving our PDF as a buffer and writing it back to Salesforce as a ContentVersion record (basically Salesforce Files) to the Lead record we retrieved in our previous query.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ffozwkujujg0nsqps6o4j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ffozwkujujg0nsqps6o4j.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can move a lot of this around and re-architect it as you see fit.  This is one of the powerful things about microservices. Mohith mentions that devs overwhelmingly agree that “services should be as dumb as possible” to avoid creating any dependencies and can exist as the simplest and most atomized version of the service. This allows you to scaffold things up with multiple services and extend things more easily.&lt;/p&gt;

&lt;p&gt;For some homework, you’ll want to check out the car-configurator LWC and explore the front end of the eCars app as well as the PDFCreateService APEX class to see how it is implemented to work with the microservice.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fjp1el93m7ha84k4ptbn1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fjp1el93m7ha84k4ptbn1.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And don’t forget to explore the&lt;a href="https://github.com/trailheadapps" rel="noopener noreferrer"&gt; sample app gallery on Github&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Concluding Thoughts&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;In several of my clients’ projects, I was brought in because the internal admin or a previous developer got “stuck” trying to implement a particular requirement that was seemingly impossible to do with Salesforce because there was no declarative solution or way to do something in APEX code. Often in these cases, an external microservice solved the problem. &lt;/p&gt;

&lt;p&gt;Once you realize that Salesforce has the capability to make web service callouts to external services, really the sky's the limit for what can be implemented when you combine Salesforce with microservices. It’s also important to remember that not only can Salesforce make callouts to external services, but external applications can make callouts to a number of Salesforce APIs to allow for bi-directional interactivity between Salesforce and third-party or homegrown applications.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fwzp43auquhv1rr8tnadh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fwzp43auquhv1rr8tnadh.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
Salesforce has so many APIs, it’s sometimes easy to forget what’s possible&lt;/p&gt;

&lt;p&gt;In the next article, we’re going to do some additional work with Salesforce and Heroku microservices in a second part for this topic.  Yes, there was too much good stuff to fit into one episode!&lt;/p&gt;

&lt;p&gt;If you haven’t already joined the official Chatter group for this series, I certainly recommend you do so. This will give you the full value of the experience and also pose questions and start discussions with the group. Oftentimes, there are valuable discussions and additional references available there such as the slides from the presentation and links to other resources and references.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://sforce.co/34Ld7xz" rel="noopener noreferrer"&gt;https://sforce.co/34Ld7xz&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;About me: I’m an 11x certified Salesforce professional who’s been running my own Salesforce consultancy for several years. If you’re curious about my backstory on accidentally turning into a developer and even competing on stage on a quiz show at one of the Salesforce conventions, you can read&lt;a href="http://green.salesforce.com/blog/2017/04/accidental-developer-to-dst17-finalist.html" rel="noopener noreferrer"&gt; this article&lt;/a&gt; I wrote for the Salesforce blog a few years ago.&lt;/p&gt;

</description>
      <category>salesforce</category>
      <category>heroku</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Automating Business Processes Using Salesforce Flows and APEX</title>
      <dc:creator>Jason Sun</dc:creator>
      <pubDate>Wed, 20 Jan 2021 00:28:45 +0000</pubDate>
      <link>https://dev.to/jasonomnivo/automating-business-processes-using-salesforce-flows-and-apex-923</link>
      <guid>https://dev.to/jasonomnivo/automating-business-processes-using-salesforce-flows-and-apex-923</guid>
      <description>&lt;h2&gt;
  
  
  &lt;strong&gt;(Heroku and Salesforce - From Idea to App, Part 7)&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;This is the seventh article documenting what I’ve learned from a series of&lt;a href="https://trailhead.salesforce.com/live/videos/a2r3k000001n2Ig/modern-app-development-on-salesforce/?ref=hackernoon.com" rel="noopener noreferrer"&gt; 13 Trailhead Live video sessions on Modern App Development on Salesforce and Heroku&lt;/a&gt;. In these articles, we’re focusing on how to combine Salesforce with&lt;a href="https://www.heroku.com/" rel="noopener noreferrer"&gt; Heroku&lt;/a&gt; to build an “eCars” app—a sales and service application for a fictitious electric car company (“Pulsar”) that allows users to customize and buy cars, service techs to view live diagnostic info from the car, and more. In case you missed my previous articles, you can find the links to them below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/jasonomnivo/modern-app-development-on-salesforce-and-heroku-206j"&gt;Modern App Development on Salesforce and Heroku&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/jasonomnivo/jumping-into-heroku-development-48ep"&gt;Jumping into Heroku Development&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/jasonomnivo/data-modeling-in-salesforce-and-heroku-data-services-569e"&gt;Data Modeling in Salesforce and Heroku Data Services&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/jasonomnivo/building-front-end-app-experiences-with-clicks-not-code-2m6e"&gt;Building Front-End App Experiences with Clicks, Not Code&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/jasonomnivo/custom-app-experiences-with-lightning-web-components-4i39"&gt;Custom App Experiences with Lightning Web Components&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/jasonomnivo/lightning-web-components-events-and-lightning-message-service-21b8"&gt;Lightning Web Components, Events and Lightning Message Service&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Just as a quick reminder: I’ve been following this Trailhead Live video series to brush up and stay current on the latest app development trends on these platforms key to my career and business. I’ll be sharing each step for building the app, what I’ve learned, and my thoughts from each session. These series reviews are both for my own edification as well as for others who might benefit from this content.&lt;/p&gt;

&lt;p&gt;The Trailhead Live sessions and schedule can be found here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://trailhead.salesforce.com/live" rel="noopener noreferrer"&gt;https://trailhead.salesforce.com/live&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Trailhead Live sessions I’m writing about can also be found at the links below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://trailhead.salesforce.com/live/videos/a2r3k000001n2Jj/modern-app-development-on-salesforce" rel="noopener noreferrer"&gt;https://trailhead.salesforce.com/live/videos/a2r3k000001n2Jj/modern-app-development-on-salesforce&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/playlist?list=PLgIMQe2PKPSK7myo5smEv2ZtHbnn7HyHI" rel="noopener noreferrer"&gt;https://www.youtube.com/playlist?list=PLgIMQe2PKPSK7myo5smEv2ZtHbnn7HyHI&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Last Time…&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;In the last session, we went into detail on Lightning Web Components (LWC) and built out a custom front-end experience by creating a custom inventory gallery for our eCars application.  We also went through all the design tools and resources available to LWC developers such as the Salesforce Lightning Design System and Lightning Web Components reference library. &lt;/p&gt;

&lt;p&gt;This time, we are shifting gears and reviewing ways to _automate _business processes. As developers, we know how to handle complex use cases with code, but Salesforce also offers a powerful, declarative way for us to do this: enter Flows.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Introduction to Salesforce Flows&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Flows in an automation tool that allows you to automate processes in Salesforce without having to write code. Although flows are considered a “declarative” or non-code method of automating processes, it’s important that developers learn how to use Flows even as some of these processes may be managed by a Salesforce Admin moving forward. It’s also important for developers to learn since Flows can integrate with APEX via invocable actions and Lightning Components.&lt;/p&gt;

&lt;p&gt;Flows offer a powerhouse of tools with easy to use drag-and-drop elements. Salesforce even offers a UI element known as Screen Flows which allows you to build a multi-page process or wizard. There are also pre-built solutions on the AppExchange that allow you to install packages with flows and combine them with your org’s pre-existing flows. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F1f7lxn3puf7y5t4o66pc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F1f7lxn3puf7y5t4o66pc.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Flows are somewhere near the middle of this spectrum&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;Automating the eCars App Using Flows&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;In our first activity with Flows and our eCars app, we will populate a &lt;em&gt;Range&lt;/em&gt;, using automation, based on a car’s price.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F98310d5kyvl6q1088jpg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F98310d5kyvl6q1088jpg.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This can also be done using APEX triggers, Process Builder or Workflow rules, but today we are going to automate this using Flows. When creating a new flow in &lt;em&gt;Setup&lt;/em&gt;, you’ll see that Flows can be triggered in multiple ways. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Screen Flows&lt;/strong&gt; give you a way to build screens for lightning pages, communities or quick actions so that users can initiate the actions and go through a series of screens with ease.  This type also supports integrating lightning web components into the flows.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Scheduled-Trigger Flows&lt;/strong&gt; allow you to specify a frequency (“this should run at 3am every day”) for when a flow should run.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Platform Event-Triggered Flows&lt;/strong&gt; offer a way to run an automation based on platform events. If you are new to Platform Events, check out this&lt;a href="https://trailhead.salesforce.com/content/learn/modules/platform_events_basics" rel="noopener noreferrer"&gt; Trailhead Module&lt;/a&gt; that will help get you up to speed.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Autolaunched Flows&lt;/strong&gt; can be invoked by APEX, process builders, other flows, or even called via the REST API and used with Einstein bots.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Record-Triggered Flows&lt;/strong&gt; are flows triggered by changes to records, such as when records are created, updated, or deleted. These are very similar to process builders, workflow rules, and APEX triggers.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F4f9yc66d2t7mrdlo4qh8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F4f9yc66d2t7mrdlo4qh8.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Today we are using the Record-Triggered Flows which allow you to run automation logic when a record is created, modified, or deleted. In the flow builder, we select when we want the flow to run. It’s important to keep a best practice in mind though: When updating the same record that you are evaluating, select &lt;em&gt;“before the record is saved&lt;/em&gt;,&lt;em&gt;”&lt;/em&gt; since selecting &lt;em&gt;“after record is saved”&lt;/em&gt; can result in recursions or infinite loops. This occurs because the &lt;em&gt;“after record is saved”&lt;/em&gt; run mode will update the record again and cause the flow to re-run.&lt;/p&gt;

&lt;p&gt;Another thing to be aware of is the order of execution when mixing different methods of automation such as APEX triggers, flows, and process builders (&lt;a href="https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_triggers_order_of_execution.htm" rel="noopener noreferrer"&gt;here it is for quick reference&lt;/a&gt;).  Oftentimes when mixing these different methods, it’s best to use an APEX trigger, since they provide the most granular control over what executes and when.&lt;/p&gt;

&lt;p&gt;There are also some limitations to be aware of for the record-trigger flow. Specifically, these Flows don’t let you use the ISCHANGED() or PRIORVALUE() functions (but this will be changing in the Spring ‘21 release). Some helpful architect documentation is available on the&lt;a href="https://quip.com/VJfCAFhEBO0W" rel="noopener noreferrer"&gt; Architect Website here&lt;/a&gt;. There, you’ll see what is currently available, as well as the roadmap for upcoming changes/releases to flows. If you have a truly complex use case, resort to APEX code. Alternatively, mix and match flows and APEX in a sensible way. For example, launch a flow and add an APEX element to it. (You can call APEX methods or Lightning Components from flows!) Because you don’t want your flow to become so complex that it is hard to maintain or debug, it’s key you check out the&lt;a href="https://architect.salesforce.com/design/decision-guides/trigger-automation/#Sayonara__Process_Builder___Workflow_Rules" rel="noopener noreferrer"&gt; Architecture Guide&lt;/a&gt; to understand when you should use what.&lt;/p&gt;

&lt;p&gt;Back in our flow, we select our object and pose the question, “When do we want this to run?” Or, phrased from a developer’s perspective: This is your “if/else statement.”&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fdnioysbeqqpvpk6av8pt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fdnioysbeqqpvpk6av8pt.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For now, we set this to “None” which will cause it to run under all conditions:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fl4iisld8q9o2prlmy7sm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fl4iisld8q9o2prlmy7sm.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We bring in the “Decision” element and review our requirements once more so we can build out this logic into our flow:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fvy4z0gfnpttpmda689f7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fvy4z0gfnpttpmda689f7.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now we can build in these conditions where we will be checking the price of the vehicle and enter the outcomes we wish to occur depending on the price.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fwk7p9ltmr27s0hkyeddn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fwk7p9ltmr27s0hkyeddn.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, we drag the “Assignment” element into our flow and go through the steps to map the range field’s corresponding value:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F5ge5a5pdqj23acx0njcl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F5ge5a5pdqj23acx0njcl.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are different options for assigning a value, and in this case, we will use “Constant:”&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Flqjdgy64yckexcde6ksa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Flqjdgy64yckexcde6ksa.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can repeat the same steps for a second “Assignment” element for medium range as well, and then finally connect our elements together:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fn6macbsdhjxtyl19vk5h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fn6macbsdhjxtyl19vk5h.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Adding lots of elements can quickly create a big of a mess on the layout, but there is a new feature called “auto-layout” which automatically cleans things up and organizes them in a neat and tidy way:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ft2d9m70hg08ynovf2o79.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ft2d9m70hg08ynovf2o79.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Even though flows are extremely powerful, there are just three logic elements in the toolbox:  Assignment, Decision and Loops.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Assignments&lt;/strong&gt; are where you can create variables and assign values to them.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Decisions&lt;/strong&gt; are like “if” statements for evaluating conditions.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Loops&lt;/strong&gt; are like “for loops” to control logic that needs to repeat until an entire list of variables has been processed (or some condition is met).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fudtgnaw01mmu6cnk7dij.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fudtgnaw01mmu6cnk7dij.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Over in the “Manager” tab, we can see all the elements created so far. These are the variables that have been created in the course of the previous steps.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ff354znk406izcu11itgz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ff354znk406izcu11itgz.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The funny thing is that pretty much every programming language I’ve come across has these same core elements just expressed with slightly different syntax. So if you’re an admin who’s already a pro at building flows and can think through the necessary logic and architecture to build them in an elegant fashion, taking the next step and developing in APEX code should be a simple transition. Essentially, you are already doing low-code programming with flows.&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;Testing and Debugging Our Flow&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;For debugging record-trigger flows, we can only test this from the record.  Test the flow we just built, save and activate it, navigate to a car record, and change the price of a car, then confirm that the range field auto-updates to the expected range value. Success!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fwc0jlecmgqhbfdvr89h5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fwc0jlecmgqhbfdvr89h5.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;More Flow Features and Other Flow Execution Types&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Back in Flow Builder, if you select a new record-triggered flow but then choose “After the record is saved,” you can see more elements in the toolkit. This execution mode has more features; now we have an “Action” as an option as well as additional data elements.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F7ynw7kstv52jdxp6v1ev.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F7ynw7kstv52jdxp6v1ev.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Note from earlier that “before save flows” are only meant to modify the same record, whereas “after save flows” allows you to handle other data operations.&lt;/p&gt;

&lt;p&gt;For the Auto-Launched Flow option, there is a “Subflow” action in our toolbox. This allows you to call a Flow from another Flow. Similar to object-oriented programming, this allows flows to be re-used in a modular fashion. An expert programmer, whether using flows or APEX, is always thinking about being parsimonious and efficient. They’d rather avoid repeating the same code or set of flow logic over and over again!&lt;/p&gt;

&lt;p&gt;Another option worth mentioning is that you can choose the security mode your flow runs. This includes a feature that lets you run the Flow with the same data security and access rules that admins have configured for the current user, or allow the flow to bypass these rules or run in “system context.”&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fu23jbblzsfcbb8569vgn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fu23jbblzsfcbb8569vgn.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With Flow Actions and Flow Screens, you can build a step-by-step wizard or custom process within Salesforce. Flow Actions allow you to create a piece of logic in APEX and bundle it so that an admin can simply drag and drop it within a Flow.  With Screen Components, you can do the same using Lightning web components, further empowering admins.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fsndj1ozrmcronwlq12yl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fsndj1ozrmcronwlq12yl.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;These flow bundles are available for those building AppExchange applications. They are also fully compatible with Continuous Integration/Continuous Deployment (CI/CD).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fe15c1hjydzcl3yejyljs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fe15c1hjydzcl3yejyljs.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Flows are stored as metadata behind the scenes that you can view them as XML. As a result, it’s versionable and can be in a Git repository (just like all of your other code) and moved/deployed between different Salesforce instances.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F5932iddywsbpo5oquiel.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F5932iddywsbpo5oquiel.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;Introduction to Salesforce APEX&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Even though there is so much that can be done with Flows, there are still cases where it’s best to use custom code and APEX. APEX is a strict-typed, object-oriented language similar to Java. In a few bullets, APEX is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Salesforce native programming language&lt;/li&gt;
&lt;li&gt;  Object oriented (classes, interfaces, inheritance)&lt;/li&gt;
&lt;li&gt;  Strongly typed language&lt;/li&gt;
&lt;li&gt;  Compiles to Java Byte Code&lt;/li&gt;
&lt;li&gt;  Includes SOQL and DML statements similar to SQL stored procedures&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now that we know what APEX is, it’s important to know when it’s appropriate to use. It’s somewhat rare to need any APEX, given all the declarative features that Salesforce provides, but certain use cases do call for it. For instance, it can be useful when you need to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Create custom transactional logic (logic that occurs over the entire transaction, not just with a single record).&lt;/li&gt;
&lt;li&gt;  Attach custom logic to another operation, such as saving a record so that it occurs whenever the operation is executed, regardless of whether the operation originated in the user interface or via a API transaction.&lt;/li&gt;
&lt;li&gt;  Create bundled APEX to be invoked from Lightning components, Visualforce pages or Flows.&lt;/li&gt;
&lt;li&gt;  Perform complex logic or validation over multiple related objects.&lt;/li&gt;
&lt;li&gt;  Create custom web services.&lt;/li&gt;
&lt;li&gt;  Create custom email services.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With the first two, it’s not necessary to use APEX, but with the last three items, there really is no alternative to APEX. In fact, one of the main uses of APEX in my current experience on client projects is to create custom REST web services. Doing so allows an external application to make POST, PUT, or GET requests to Salesforce and have the requests processed in a custom fashion.&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;Automating Tasks for the eCars App with APEX&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Our example use case for APEX and our eCars app will be to create a task for our sales reps after a vehicle status is set to “sold.”&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fc7ba0o8dn86au9evi6b2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fc7ba0o8dn86au9evi6b2.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When first starting out doing development, I did a lot of copy-pasting and editing existing code.  There is no shame in this; it’s all part of the learning process. Luckily, in the &lt;a href="https://github.com/trailheadapps/apex-recipes" rel="noopener noreferrer"&gt;APEX Recipes Github repository&lt;/a&gt;, we can find some APEX Recipes with bite-sized snippets of code for almost everything that you might need. The code samples found here are also “production quality,” so it would be a useful exercise to review and compare it with any existing code you’ve written to gain some insights into what Salesforce considers best practices.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ffxrys6xwzygcjp8ce0ow.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ffxrys6xwzygcjp8ce0ow.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The recipes include integrations, SOQL, DML, and other use cases. Each of these recipes is paired with documentation. The recipes also encompass best practices around writing secure code. When writing APEX, we sometimes want the permissions that are configured for an object to be enforced. This needs to be handled explicitly in code— a useful recipe to review is the “CanTheUser” recipe.&lt;/p&gt;

&lt;p&gt;It’s important to note that even though you &lt;em&gt;can&lt;/em&gt; create multiple APEX triggers for an object, you should never &lt;em&gt;do&lt;/em&gt; so. If you did, it would be easy to quickly lose control over the execution of the transaction, as the order that the triggers are fired is not guaranteed. Therefore, it is recommended you write only one trigger per object and have a delegator pattern in place—that is where a TriggerHandler comes in.  A common pattern that I use for all triggers and handler classes is as follows. You can see that having a dedicated handler method allows for more granular control in each execution context.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;trigger ObjectTrigger on Object__c (before insert, before update, after insert, after update, after delete, after undelete) {
    if(trigger.isBefore){
        if(trigger.isInsert){
        ObjectTriggerHandler.handleBeforeInsert(trigger.new);       
    }
    else if(trigger.isUpdate){
            ObjectTriggerHandler.handleBeforeUpdate(trigger.newMap, trigger.oldMap);       
    }   
}
else if(trigger.isAfter){
        if(trigger.isInsert){
            ObjectTriggerHandler.handleAfterInsert(trigger.newMap);
    }
    else if(trigger.isUpdate){
            ObjectTriggerHandler.handleAfterUpdate(trigger.newMap, trigger.oldMap);       
    }
    else if(trigger.isDelete){
            ObjectTriggerHandler.handleAfterDelete(trigger.oldMap);       
    }
    else if(trigger.isUndelete){
            ObjectTriggerHandler.handleAfterUndelete(trigger.newMap);       
    }
}
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using a combination of what we’ve learned so far and the APEX Recipes library, it should be relatively straightforward to implement the task automation for the eCars app. If anyone is having problems, the&lt;a href="https://sforce.co/34Ld7xz" rel="noopener noreferrer"&gt; Chatter group dedicated to this series&lt;/a&gt; would be a good place to ask for help with your code.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Concluding Thoughts&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;With so many ways to implement a particular use case, it’s important that we talk about which tool to use when and to review best practices. Do you use APEX only, Flows only or a hybrid approach? If you’re unsure, it’s useful to refer back to the&lt;a href="https://www.google.com/url?q=https://architect.salesforce.com/design/decision-guides/trigger-automation&amp;amp;sa=D&amp;amp;ust=1609962960270000&amp;amp;usg=AOvVaw2twIoSkDb2LXaV9INvdaTB" rel="noopener noreferrer"&gt; Architecture Guide&lt;/a&gt; Quip document.  A summary of the key deciding factors is as follows:&lt;/p&gt;

&lt;p&gt;You should typically choose the tool that allows you to build and maintain the solution at a low cost:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  If you have APEX developers available and have well-established CI/CD and trigger frameworks in place, adding Flows to the mix can unnecessarily add overhead.&lt;/li&gt;
&lt;li&gt;  If your application will be maintained by admins or non-developers in the future and there is less access to developers, then Flows may be the best choice.&lt;/li&gt;
&lt;li&gt;  If you have a combination of devs and admins, you can consider using flow triggers with complex multi-record processing logic in an APEX layer that is exposed as services/actions for flows.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At the time of this writing, APEX developers are in short supply as compared to Salesforce admins, so it’s usually natural to avoid APEX for as long as possible. However, in certain cases, it’s very easy for flows to quickly get too complex, out of control, and unmaintainable. This is especially true if thought isn’t put into how the flows are architected and organized. It’s also important to revisit existing flows periodically to see if they can be refactored to be more modular or maintainable. I’ve seen many orgs overuse flows when a little bit of APEX could have been a more effective solution. When that happens, the organization has to spend a great deal of resources trying to fix/refactor a mess of flows once things start breaking and error messages start popping up. As a result, an ounce of prevention in this case is worth many pounds (and hours) of technical debt!&lt;/p&gt;

&lt;p&gt;In the next article, we’re going to look at scaling Salesforce applications with microservices on Heroku and building using an event-based architecture.&lt;/p&gt;

&lt;p&gt;If you haven’t already joined the official Chatter group for this series, I certainly recommend you do so. That way, you can get the full value of the experience and also pose questions and start discussions with the group. Oftentimes, there are valuable discussions and additional references available there such as the slides from the presentation and links to other resources and references.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://sforce.co/34Ld7xz" rel="noopener noreferrer"&gt;https://sforce.co/34Ld7xz&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;About me:  I’m an 11x certified Salesforce professional who’s been running my own Salesforce consultancy for several years. If you’re curious about my backstory on accidentally turning into a developer and even competing on stage on a quiz show at one of the Salesforce conventions, you can read&lt;a href="http://green.salesforce.com/blog/2017/04/accidental-developer-to-dst17-finalist.html" rel="noopener noreferrer"&gt; this article&lt;/a&gt; I wrote for the Salesforce blog a few years ago.&lt;/p&gt;

</description>
      <category>heroku</category>
      <category>salesforce</category>
    </item>
    <item>
      <title>Lightning Web Components, Events and Lightning Message Service</title>
      <dc:creator>Jason Sun</dc:creator>
      <pubDate>Mon, 28 Dec 2020 16:57:51 +0000</pubDate>
      <link>https://dev.to/jasonomnivo/lightning-web-components-events-and-lightning-message-service-21b8</link>
      <guid>https://dev.to/jasonomnivo/lightning-web-components-events-and-lightning-message-service-21b8</guid>
      <description>&lt;h2&gt;
  
  
  (Heroku and Salesforce - From Idea to App, Part 6)
&lt;/h2&gt;

&lt;p&gt;This is the sixth article documenting what I’ve learned from a series of&lt;a href="https://trailhead.salesforce.com/live/videos/a2r3k000001n2Ig/modern-app-development-on-salesforce/?ref=hackernoon.com"&gt; 12 Trailhead Live video sessions on Modern App Development on Salesforce and Heroku&lt;/a&gt;. In these articles, we’re focusing on how to combine Salesforce with&lt;a href="https://www.heroku.com/"&gt; Heroku&lt;/a&gt; to build an “eCars” app—a sales and service application for a fictitious electric car company (“Pulsar”) that allows users to customize and buy cars, service techs to view live diagnostic info from the car, and more. In case you missed my previous articles, you can find the links to them below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/jasonomnivo/modern-app-development-on-salesforce-and-heroku-206j"&gt;Modern App Development on Salesforce and Heroku&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/jasonomnivo/jumping-into-heroku-development-48ep"&gt;Jumping into Heroku Development&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/jasonomnivo/data-modeling-in-salesforce-and-heroku-data-services-569e"&gt;Data Modeling in Salesforce and Heroku Data Services&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/jasonomnivo/building-front-end-app-experiences-with-clicks-not-code-2m6e"&gt;Building Front-End App Experiences with Clicks, Not Code&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/jasonomnivo/custom-app-experiences-with-lightning-web-components-4i39"&gt;Custom App Experiences with Lightning Web Components&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Just as a quick reminder: I’ve been following this Trailhead Live video series to brush up and stay current on the latest app development trends on these platforms that are key for my career and business. I’ll be sharing each step for building the app, what I’ve learned, and my thoughts from each session. These series reviews are both for my own edification as well as for others who might benefit from this content.&lt;/p&gt;

&lt;p&gt;The Trailhead Live sessions and schedule can be found here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://trailhead.salesforce.com/live"&gt;https://trailhead.salesforce.com/live&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Trailhead Live sessions I’m writing about can also be found at the links below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://trailhead.salesforce.com/live/videos/a2r3k000001n2Jj/modern-app-development-on-salesforce"&gt;https://trailhead.salesforce.com/live/videos/a2r3k000001n2Jj/modern-app-development-on-salesforce&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/playlist?list=PLgIMQe2PKPSK7myo5smEv2ZtHbnn7HyHI"&gt;https://www.youtube.com/playlist?list=PLgIMQe2PKPSK7myo5smEv2ZtHbnn7HyHI&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Last Time…
&lt;/h2&gt;

&lt;p&gt;In the last session, we went into detail about considerations and tools related to customizing app experiences, from point-and-click methods all the way to fully custom code.  However, we only briefly touched on the featured go-to custom code framework: Lightning Web Components, or LWC. &lt;/p&gt;

&lt;p&gt;This time, we’re taking a deeper look into LWC and also covering how to communicate between components in our eCars app using Events and the Lightning Message Service.&lt;/p&gt;

&lt;h2&gt;
  
  
  Like Normal Web Components… but With More!
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://lwc.dev/"&gt;LWC&lt;/a&gt; are built on top of regular &lt;a href="https://developer.mozilla.org/en-US/docs/Web/Web_Components"&gt;web components&lt;/a&gt; (WC) which almost every web application developer should be familiar with. In a previous article, I commented on how smart it is for Salesforce to move from SFDC-specific frameworks (like Visualforce) to LWC, since this allows most web developers to build on the platform with less of a learning curve. On top of that, web components are modern, interoperable, future-proof, and backwards compatible. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--QeUusiHK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/qaz0864lxkxpmy66tsw9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--QeUusiHK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/qaz0864lxkxpmy66tsw9.png" alt="Lightning Web Components Framework"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The idea underpinning LWC is the open-source framework that has a compiler and Lightning-specific properties. This provides what &lt;a href="https://twitter.com/msrivastav13"&gt;Mohith Shrivastava&lt;/a&gt; calls “sugar” on top of a web component.  &lt;/p&gt;

&lt;p&gt;The verbose WC syntax then becomes really simple; we can add styling using the Salesforce Lightning Design System (SLDS) as well as Metadata.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--THlAQZvn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/bjntcy0ha5ys6843oyl1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--THlAQZvn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/bjntcy0ha5ys6843oyl1.png" alt="Sugar on top of Web Components"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Sweet!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;For those of you, like me, who may have come from “Visualforce/APEX land” and find LWC somewhat of a fresh concept, remember this: when you are learning LWC, you are learning the standard web components as well. Two birds, one sweet framework.&lt;/p&gt;

&lt;p&gt;Another important tidbit for those of us coming from APEX/Visualforce: JavaScript and thus LWC are CaSe sEnsiTive so if you’re used to APEX code being case insensitive, save yourself a lot of debugging and don’t forget to use camelCase or kebab-case where needed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building Out the Enhanced eCars Inventory Gallery
&lt;/h2&gt;

&lt;p&gt;Let’s jump into the first activity, where our goal is to build our custom inventory list experience for the eCars app. In the previous article, we created a prototype using a Salesforce Lightning Design System (SLDS) plug-in for Sketch.  We also used standard SLDS base components to arrive at this enhanced layout:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Igxjrx21--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/36zmom6dj0rysq5n80iz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Igxjrx21--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/36zmom6dj0rysq5n80iz.png" alt="eCars Gallery View"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Certainly nicer than a bland list view&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;We will build in our IDE of choice, Visual Studio Code.  You’ll need a scratch org and Salesforce-specific extensions for VS code to get started. If you are just finding this article now and are not yet set up with a Salesforce developer account, dev hub, and scratch orgs, go ahead and jump to the &lt;a href=""&gt;first article of the series&lt;/a&gt; to get those things set up. Once that’s done, you’re up and running and ready to develop.&lt;/p&gt;

&lt;p&gt;When building LWC, the component-reference documentation is GOAT (greatest of all time). Salesforce has invested a lot in giving you “pre-baked components that have a lot of functionality,” including providing HTML, CSS, and Javascript code out-of-the-box. These are largely the same components you’d find in SLDS, so the design process and the code implementation are going to flow naturally. One of the components we used for the Sketch design is available in the component reference, of course: the Lightning Card.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--AL5npQdZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/2llhnjoxu0kfswsz26w0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--AL5npQdZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/2llhnjoxu0kfswsz26w0.png" alt="SLDS Web Components"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;An all-you-can-copy-and-paste component buffet&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;We can proceed by just pulling in the pre-baked code for the Lightning Card component we want to use. At this point, it’s useful to understand the term “slot.” A “slot” is a placeholder in components where you can add your own component or HTML mark-up. Mohith also reviews badges documentation and pulls in a stand-in image. With a refresh to our local dev server (Code Preview), we can see the beginnings of the inventory card.&lt;/p&gt;

&lt;p&gt;We can then expand on this single inventory card component and create iterations of each card that will pass data from the Vehicle__c Salesforce custom object records to this new inventory component. We can bind the data properties from Salesforce data to our component using the @api decorator.&lt;/p&gt;

&lt;p&gt;LWC adds a lot of utilities for you to create flow control for apps including repeaters and conditionals. You can check them out at &lt;a href="//lwc.dev"&gt;lwc.dev&lt;/a&gt; where you’ll learn all the fundamentals like templates, data binding, and development lifecycle.&lt;/p&gt;

&lt;h2&gt;
  
  
  Design Help for Developers
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--up8MKOza--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/c2cswim8qhum52o8gqm3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--up8MKOza--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/c2cswim8qhum52o8gqm3.png" alt="Design Help for Developers"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Developers and designers are usually not the same people, and the skillsets don’t always overlap. As a result, it’s very nice to have libraries and design systems like SLDS and the LWC component reference, since they take care of a lot of the design thinking for us developers. But of course, if you are a developer/designer hybrid unicorn and have the CSS background, you can build onto SLDS with your own designs and create amazing interfaces.&lt;/p&gt;

&lt;p&gt;In the documentation, we have a lot at our fingertips. We even have a playground to learn about different ways to size our layouts; we are encouraged to try different options to understand what type of layouts are actually possible. Developers even have the option to build out layouts that are automatically responsive.&lt;/p&gt;

&lt;p&gt;I personally love what the SLDS has done: it’s given us utilities so that we don’t have to actually worry about them. For example, if we want to add some padding somewhere, we can look at the classes in the documentation, find the appropriate one, and simply copy-paste the class to our component. Using on-page or in-line CSS should be a rare case and avoided whenever possible.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--J3WZxiQT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/9347ojczhc9a3vu0dhdv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--J3WZxiQT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/9347ojczhc9a3vu0dhdv.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Back to App Building
&lt;/h2&gt;

&lt;p&gt;Moving forward in the walkthrough, we get our component set up and preview it locally:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8ivciwBe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/fsv54luhmvusemiyttoi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8ivciwBe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/fsv54luhmvusemiyttoi.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Looks like we are almost there!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;There are certain properties in Lighting Layouts that we can use to our advantage. In this example, we want multiple rows, which means we get to play with the size element. In VS code, if the LWC extension is installed, hovering over an element shows all its properties. Then we can start typing it in, find what we need, and let the auto-complete save us time.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Ym6oUJCB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/3rgj5zzz79pzp6lw5uh3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Ym6oUJCB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/3rgj5zzz79pzp6lw5uh3.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;This will save me lots of Google searches&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Events in Lightning Components
&lt;/h2&gt;

&lt;p&gt;We need Events to handle transmitting data in LWC between separate components. That’s because they do not automatically communicate with each other, even if they are organized as parent-child components. (Maybe the child is a broody teenager?) But jokes aside, this is by design and for security reasons. That way, foreign components embedded in the same page cannot “spy” on another component’s data.&lt;/p&gt;

&lt;p&gt;The important thing to remember with Events in LWC is that “if you do not have a strategy, you can quickly mess up your architecture without following a consistent design pattern.” The best practice for child-to-parent components is to always use Events. In our eCars inventory gallery, we add a function where clicking one image will mute or “blur” all others on the screen. The blur effect is done in CSS, but handling the event to blur/unblur the appropriate cards requires Events and JavaScript.&lt;/p&gt;

&lt;p&gt;We create a JavaScript event (new CustomEvent = ‘cardselect’) and pass the vehicle’s VIN so we can identify which element is being clicked. We dispatch the Event on clicking the card, but how can we have the card component listen for this? We can go into the HTML element for the inventory-card and add an “oncardselect” property calling a function, our handler.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--X_aStzq0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/orhgu714wbp1eb0fuvjf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--X_aStzq0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/orhgu714wbp1eb0fuvjf.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can then add our handler to our JavaScript with a map function to return the modified element, followed by the @track decorator to ensure we have reactivity when we are interacting with our app.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---VpTGFLt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/olk9c2m70f69uo34g5o7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---VpTGFLt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/olk9c2m70f69uo34g5o7.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
_ Lightning cards go blurrrrrr_&lt;/p&gt;

&lt;h2&gt;
  
  
  Concluding Thoughts
&lt;/h2&gt;

&lt;p&gt;I remember the first time I went through a Visualforce tutorial. I needed to review existing working example code, modify it, break it, and build it back up again. I anticipate I’ll have to do the same with LWC, and also work through some practical exercises to build up experience and confidence with the framework. I would love to hear from those who are familiar with regular web components on how similar this is to them and how quick the transition is from regular WC to LWC.  Luckily, I have a backlog of Visualforce pages from Salesforce orgs that I manage—they could use some conversion to Lightning Web Components. I reckon I’ll get plenty of practice with LWC that way!  There is also a &lt;a href="https://github.com/trailheadapps/visualforce-to-lwc"&gt;nice sample app on github&lt;/a&gt; from the Developer Advocate Team that actually demonstrates how to do this.&lt;/p&gt;

&lt;p&gt;In the next article, we’re going to look at automating back-end processes and logic for our eCars app using Flows and APEX.&lt;/p&gt;

&lt;p&gt;If you haven’t already joined the official Chatter group for this series, I certainly recommend you do so. That way, you can get the full value of the experience and also pose questions and start discussions with the group. Oftentimes, there are valuable discussions and additional references available there such as the slides from the presentation and links to other resources and references.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://sforce.co/34Ld7xz"&gt;https://sforce.co/34Ld7xz&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;About me:  I’m an 11x certified Salesforce professional who’s been running my own Salesforce consultancy for several years. If you’re curious about my backstory on accidentally turning into a developer and even competing on stage on a quiz show at one of the Salesforce conventions, you can read&lt;a href="http://green.salesforce.com/blog/2017/04/accidental-developer-to-dst17-finalist.html"&gt; this article&lt;/a&gt; I wrote for the Salesforce blog a few years ago.&lt;/p&gt;

</description>
      <category>heroku</category>
      <category>salesforce</category>
    </item>
    <item>
      <title>Custom App Experiences with Lightning Web Components</title>
      <dc:creator>Jason Sun</dc:creator>
      <pubDate>Thu, 17 Dec 2020 02:54:04 +0000</pubDate>
      <link>https://dev.to/jasonomnivo/custom-app-experiences-with-lightning-web-components-4i39</link>
      <guid>https://dev.to/jasonomnivo/custom-app-experiences-with-lightning-web-components-4i39</guid>
      <description>&lt;h2&gt;
  
  
  (Heroku and Salesforce - From Idea to App, Part 5)
&lt;/h2&gt;

&lt;p&gt;This is the fifth article documenting what I’ve learned from a series of&lt;a href="https://trailhead.salesforce.com/live/videos/a2r3k000001n2Ig/modern-app-development-on-salesforce/?ref=hackernoon.com"&gt; 10 Trailhead Live video sessions on Modern App Development on Salesforce and Heroku&lt;/a&gt;. In these articles we’re focusing on how to combine &lt;a href="https://developer.salesforce.com"&gt;Salesforce&lt;/a&gt; with&lt;a href="https://www.heroku.com/"&gt; Heroku&lt;/a&gt; to build an “eCars” app—a sales and service application for a fictitious electric car company (“Pulsar”) that allows users to customize and buy cars, service techs to view live diagnostic info from the car, and more. In case you missed my previous articles, you can find the links to them below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/jasonomnivo/modern-app-development-on-salesforce-and-heroku-206j"&gt;Modern App Development on Salesforce and Heroku&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/jasonomnivo/jumping-into-heroku-development-48ep"&gt;Jumping into Heroku Development&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/jasonomnivo/data-modeling-in-salesforce-and-heroku-data-services-569e"&gt;Data Modeling in Salesforce and Heroku Data Services&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/jasonomnivo/building-front-end-app-experiences-with-clicks-not-code-2m6e"&gt;Building Front-End App Experiences with Clicks, Not Code&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Just as a quick reminder: I’ve been following this Trailhead Live video series to brush up and stay current on the latest app development trends on these platforms that are key for my career and business. I’ll be sharing each step for building the app, what I’ve learned, and my thoughts from each session. These series reviews are both for my own edification as well as for others who might benefit from this content.&lt;/p&gt;

&lt;p&gt;The Trailhead Live sessions and schedule can be found here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://trailhead.salesforce.com/live"&gt;https://trailhead.salesforce.com/live&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Trailhead Live sessions I’m writing about can also be found at the links below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://trailhead.salesforce.com/live/videos/a2r3k000001n2Jj/modern-app-development-on-salesforce"&gt;https://trailhead.salesforce.com/live/videos/a2r3k000001n2Jj/modern-app-development-on-salesforce&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/playlist?list=PLgIMQe2PKPSK7myo5smEv2ZtHbnn7HyHI"&gt;https://www.youtube.com/playlist?list=PLgIMQe2PKPSK7myo5smEv2ZtHbnn7HyHI&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Previously…
&lt;/h2&gt;

&lt;p&gt;Last session, we covered some no-code, point-and-click ways to control and customize the UI/UX experience on the Salesforce platform when building apps. This time, we are looking at tools for building completely custom front-end experiences using code, and will apply those tools to our eCars app to create a custom UI.&lt;/p&gt;

&lt;p&gt;Looking at the range of possibilities for customization, you could put creating the eCars UI on a scale from no-code to all-code.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--yV-PtX12--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/p3zh9mjtukf09rgbnqfd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yV-PtX12--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/p3zh9mjtukf09rgbnqfd.png" alt="low code to high code"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;C and D only come into play about 20% of the time&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In my experience building Salesforce apps for my clients, I’ve found that Salesforce’s point-and-click tools usually satisfy 80% or more of the project’s requirements. In the other 20% of cases, some kind of custom Visualforce page or Lightning Component is needed for a particular use case. This is especially true when looking at internal-facing apps. &lt;/p&gt;

&lt;p&gt;On the other hand, when building a public-facing customer app, or a partner-community portal on Salesforce Community Cloud, it’s about a 50/50 split. This is usually due to a company’s branding needs for their public-facing experience. I expect this ratio to shift even more in the direction of low-code or no-code in the future since Salesforce is always releasing new ways to empower the point-and-click methodologies of the platform.  Finally, in certain cases, it actually makes sense to build parts of the app on Heroku when you get to very large scale B2C applications (greater than 50 million active users) with the added benefit of being able to choose the UI framework of your choice in Heroku.&lt;/p&gt;

&lt;h2&gt;
  
  
  Customization Considerations
&lt;/h2&gt;

&lt;p&gt;Since implementing, updating, or undoing the point-and-click customizations are so fast, I’ve found it’s typically best to build out the minimally viable product (or MVP) for the application using point-and-click methods. Then, I extend certain parts of the application with custom code where needed. In my experience, beginning with an entirely custom build has only led to pain and suffering, as well as a much larger project budget.&lt;/p&gt;

&lt;p&gt;Every now and then, a use case is overwhelmingly compelling for some kind of customization, or the client or project stakeholders insist on some kind of custom experience. With the latter case, I always try to talk them out of it and also warn them of the added costs of building, maintaining, and updating the custom code. If we don’t carefully control and document the code (and rarely do projects leave room for this), things can quickly go south as changes on top of “enhancements” pile up on the legacy code.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zQ_4jsWM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/a6gnhlbap7o8wr67iipg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zQ_4jsWM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/a6gnhlbap7o8wr67iipg.png" alt="explaining legacy code"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;This happens surprisingly often&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;To try and avoid this situation, it’s always good to put the customization use case through its paces via a framework to see if it’s truly necessary. In the video series, Mohith, our Salesforce Developer Advocate, gives us a nice three-point checklist to go through to see if customization is necessary.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--p-k483X9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/4pijdsuekcore0jhajwb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--p-k483X9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/4pijdsuekcore0jhajwb.png" alt="When to consider customization"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Checkpoint 2.5: See if a third-party&lt;a href="https://appexchange.salesforce.com/components"&gt; Lightning Component on the AppExchange&lt;/a&gt; might work&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  SLDS and Design Tools
&lt;/h2&gt;

&lt;p&gt;Let’s suppose we’ve gone through the process and found a compelling and proper use case to use custom code to create a custom experience for the app. We don’t just start putting pencil to paper and start coding. Oftentimes, the app feedback I get from stakeholders is neither specific nor detailed enough to be actionable. It’s usually something more ambiguous like “this page doesn’t show enough information” or “the UI is too clunky for my users to perform X process.” &lt;/p&gt;

&lt;p&gt;At that point, the real fun begins. We have to tease out what the users really need to be built out for them through a process of sketching, prototyping, and iterating---all before actually committing to code. Luckily, there are a number of tools that can help with this process and make sure that we hit the sweet spot when it comes to working up a custom design.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--VJc4GQX9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ewueg4jp84qu30hsptsd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--VJc4GQX9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ewueg4jp84qu30hsptsd.png" alt="Design sweet spot"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;It’s surprisingly easy to let these things get totally disconnected&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Salesforce Lightning Design System (SLDS)
&lt;/h3&gt;

&lt;p&gt;I’d describe the&lt;a href="https://www.lightningdesignsystem.com/"&gt; Salesforce Lightning Design System&lt;/a&gt;, or SLDS for short, as a cheat-sheet of all the UI components that comprise Salesforce Lightning Experience.  Similar to Bootstrap— which some web developers may be familiar with— it’s an entire library of design guidelines, component blueprints, utilities, and design tokens, along with code samples. All the HTML and CSS has been provided so a developer can simply go through the SLDS library and pick out components to piece together for the build.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--L4Du7Nix--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/tel88p3fzohy0p1uxxvp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--L4Du7Nix--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/tel88p3fzohy0p1uxxvp.png" alt="SLDS Modal Header"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;An example modal component with HTML sample and CSS classes already provided&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  SLDS Plugin for Sketch
&lt;/h3&gt;

&lt;p&gt;There is also an SLDS plugin for Sketch that allows Sketch users to get access to all the components in SLDS. As a result, designers can quickly prototype something with SLDS components using the drag-and-drop design tools in Sketch. The only caveat here is that this plugin is currently only available for MacOS.&lt;/p&gt;

&lt;h3&gt;
  
  
  UI Toolkits for Sketch, Figma, and Framer
&lt;/h3&gt;

&lt;p&gt;Fortunately, those who have something other than MacOS, or use something other than Sketch, can download the SLDS UI Toolkits to get the same components. Figma also happens to be a very popular design tool that I’ve come across several times while working with designers.&lt;/p&gt;

&lt;h3&gt;
  
  
  SLDS Validator for VS Code
&lt;/h3&gt;

&lt;p&gt;Finally, the SLDS Validator is an extension for VS Code. It makes sure that if one gets deep into custom-code land, the code produced remains SLDS compliant and compatible with Salesforce Lightning Experience.&lt;/p&gt;

&lt;p&gt;All of the aforementioned tools and more can be found on the&lt;a href="https://www.lightningdesignsystem.com/tools/overview/"&gt; Tools section of the Salesforce Lightning Design System site.&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Improving the eCars App’s Inventory List View
&lt;/h2&gt;

&lt;p&gt;In the context of Pulsar’s eCars app, we have an example use case for a bespoke front-end experience that requires some custom development. We’re presented with the following user story:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;“Pulsar uses eCars Sample gallery apps. The current inventory page uses a standard list view to display inventory items.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Agents using the app have expressed that it would be visually helpful to them if they can see the car images for each inventory. The status field is not obvious and agents have asked to make it visually appealing.”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--EWtkCetr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/eguadvgvk3g9nhpyszlv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--EWtkCetr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/eguadvgvk3g9nhpyszlv.png" alt="current design"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;This gets the job done, but is certainly not visually compelling&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I find that many clients and stakeholders are “show me” people. I need to put something visual in front of them to start collecting substantive feedback. If you go to the approximate halfway mark of the video, you get to see, first-hand, how we use Sketch and the SLDS plugin together to create our improved eCars wireframe after about 15 minutes of point-and-click work! And with the code samples already provided by the SLDS library, the developers will be happy that the designers didn’t go way off into left field with their designs. Put simply: a win-win.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--TKRe_oGw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/fg0e0nnpgrde4qilw7zq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TKRe_oGw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/fg0e0nnpgrde4qilw7zq.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Fifteen minutes of wireframing, hours of meetings and discussions saved&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Concluding Thoughts and Other Helpful Resources
&lt;/h2&gt;

&lt;p&gt;The session concluded with an interview with a real-life product designer, Brian Winterhoff from Carmax. I came away with two learnings from the interview :&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;There is often a learning curve for designers when transitioning from traditional web app development to Salesforce. With web app design, there is  more of an empty canvas, whereas Salesforce provides some of the base UI. However, this apparent constraint actually allows for better collaboration between designers and developers when working in the shared context of the Salesforce Platform.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Even after going down the route of prototyping and iterating with designers, more often than not, they are able to find a non-code solution that works for the use case.  This just goes to show that just because you’ve committed to wireframing a custom design, it doesn’t mean that custom code will be necessary to implement it.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;After watching this session, &lt;a href="https://www.sketch.com/"&gt;the sketch tool&lt;/a&gt; is definitely something I’m going to start using more, now that I’ve seen how simple it is to use in conjunction with SLDS. I’m thinking this is going to save me (and a lot of other people) time when it comes to nailing down a custom front-end experience design.&lt;/p&gt;

&lt;p&gt;For more information and specific practice on some of the topics covered, check out the links to the resources below:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://trailhead.salesforce.com/content/learn/modules/ux-research-basics"&gt; UX Research Basics&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://trailhead.salesforce.com/en/content/learn/modules/ux-personas-for-salesforce"&gt; UX Personas for Salesforce&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://trailhead.salesforce.com/content/learn/modules/app-design-and-prototyping/know-the-design-roles-and-best-practices"&gt; App Design and Prototypes&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=K5i9zMzVlzM"&gt; Developer Quick Takes: Explaining Shadow DOMBuild Flows with Flow Builder&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=6rK3AyxE-54"&gt; Developer Quick Takes: Custom Elements and HTML Templates&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://trailhead.salesforce.com/live/videos/a2r3k000001n2Iv/slds-deep-dive-and-best-practices"&gt; SLDS Best Practices&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://trailhead.salesforce.com/en/content/learn/superbadges/superbadge_lwc_specialist"&gt; Lightning Web Component Specialist Super Badge&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the next article, we’re going to continue on with Lightning Web Components and focus on a specific topic: communicating between separate LWCs using Events.&lt;/p&gt;

&lt;p&gt;If you haven’t already joined the official Chatter group for this series, I certainly recommend you do so. That way, you can get the full value of the experience and also pose questions and start discussions with the group. Oftentimes, there are valuable discussions and additional references available there such as the slides from the presentation and links to other resources and references.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://sforce.co/34Ld7xz"&gt;https://sforce.co/34Ld7xz&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;About me:  I’m an 11x certified Salesforce professional who’s been running my own Salesforce consultancy for several years. If you’re curious about my backstory on accidentally turning into a developer and even competing on stage on a quiz show at one of the Salesforce conventions, you can read&lt;a href="http://green.salesforce.com/blog/2017/04/accidental-developer-to-dst17-finalist.html"&gt; this article&lt;/a&gt; I wrote for the Salesforce blog a few years ago.&lt;/p&gt;

</description>
      <category>salesforce</category>
      <category>heroku</category>
      <category>ux</category>
      <category>design</category>
    </item>
    <item>
      <title>Building Front-End App Experiences with Clicks, Not Code</title>
      <dc:creator>Jason Sun</dc:creator>
      <pubDate>Sat, 05 Dec 2020 04:50:55 +0000</pubDate>
      <link>https://dev.to/jasonomnivo/building-front-end-app-experiences-with-clicks-not-code-2m6e</link>
      <guid>https://dev.to/jasonomnivo/building-front-end-app-experiences-with-clicks-not-code-2m6e</guid>
      <description>&lt;h2&gt;
  
  
  (Heroku and Salesforce - From Idea to App, Part 4)
&lt;/h2&gt;

&lt;p&gt;This is the fourth article documenting what I’ve learned from a series of&lt;a href="https://trailhead.salesforce.com/live/videos/a2r3k000001n2Ig/modern-app-development-on-salesforce/?ref=hackernoon.com"&gt; 10 Trailhead Live video sessions on Modern App Development on Salesforce and Heroku&lt;/a&gt;. In these articles, we’re focusing on how to combine Salesforce with&lt;a href="https://www.heroku.com/"&gt; Heroku&lt;/a&gt; to build an “eCars” app—a sales and service application for a fictitious electric car company (“Pulsar”) that allows users to customize and buy cars, service techs to view live diagnostic info from the car, and more. In case you missed my previous articles, you can find the links to them below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/jasonomnivo/modern-app-development-on-salesforce-and-heroku-206j"&gt;Modern App Development on Salesforce and Heroku&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/jasonomnivo/jumping-into-heroku-development-48ep"&gt;Jumping into Heroku Development&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/jasonomnivo/data-modeling-in-salesforce-and-heroku-data-services-569e"&gt;Data Modeling in Salesforce and Heroku Data Services&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Just as a quick reminder: I’ve been following this Trailhead Live video series to brush up and stay current on the latest app development trends on these platforms that are key to my career and business. I’ll be sharing each step for building the app, what I’ve learned, and my thoughts from each session. These series reviews are both for my own edification as well as for others who might benefit from the content.&lt;/p&gt;

&lt;p&gt;The Trailhead Live sessions and schedule can be found here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://trailhead.salesforce.com/live"&gt;https://trailhead.salesforce.com/live&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Trailhead Live sessions I’m writing about can also be found at the links below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://trailhead.salesforce.com/live/videos/a2r3k000001n2Jj/modern-app-development-on-salesforce"&gt;https://trailhead.salesforce.com/live/videos/a2r3k000001n2Jj/modern-app-development-on-salesforce&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/playlist?list=PLgIMQe2PKPSK7myo5smEv2ZtHbnn7HyHI"&gt;https://www.youtube.com/playlist?list=PLgIMQe2PKPSK7myo5smEv2ZtHbnn7HyHI&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Last time…
&lt;/h2&gt;

&lt;p&gt;Last session, we did some data modeling in Salesforce using point-and-click methods and also went over some of the data modeling and scalability features of the Heroku platform. If you remember from the last article, I absolutely think that proper data modeling at the outset is critical to setting up an app for success.&lt;/p&gt;

&lt;p&gt;In this episode, we’re looking at a topic that is paradoxically both anathema to me_ and_ something that makes me love the Salesforce platform: creating front-end app experiences. I promise this will make sense as we get deeper into the article.&lt;/p&gt;

&lt;p&gt;Ever since I first got into app development, designing and building front-end experiences for an app or website has probably been my least enjoyable experience. With back-end development, things either worked the way they should, or you had clear bugs or errors: there was no middle ground. On the other hand, I found front-end to be far too subjective of a topic for my liking—everyone had a different opinion about how something should flow, how it should look, whether to use rounded or square edges, which shade of blue would get more clicks, etc. Then, when you finally get to release the end product after much colorful debate, a group of users out in the wild invariably figures out a way to get confused by the front-end experience you worked so hard on.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1XJfoJ5C--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/dsxcniozc4du0r4wuhds.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1XJfoJ5C--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/dsxcniozc4du0r4wuhds.jpeg" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;The fact that there is massive controversy over this meme is why I dislike working on both&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;However, I think my early distaste for front-end related things is actually something that drew me deeper into the Salesforce ecosystem. I was naturally attracted to the platform’s meta-data driven architecture that allows me to quickly get an app concept up-and-running with a working and extensively customizable user interface without having to write a bunch of front-end HTML, CSS, and Javascript.  Many of my clients are very visual in the way they process information, and oftentimes they need something in front of them they can play around with and “kick the tires” on before they’re able to provide substantive feedback on ways we can improve their experience. Being able to prototype this way has saved me countless hours iterating on designs.&lt;/p&gt;

&lt;p&gt;As a result, this session really had me thinking about how much one can do with the front-end experience of a Salesforce app before having to do anything with code.&lt;/p&gt;

&lt;p&gt;Let’s look at some of those features in the context of our eCars app.&lt;/p&gt;

&lt;h2&gt;
  
  
  Personalizing and Branding the Salesforce App
&lt;/h2&gt;

&lt;p&gt;A nice feature that’s been added to the Salesforce Lightning Experience interface is the Themes and Branding section of the User Interface area of app setup. Without needing code to customize the color palette, banners, logo, and images, we can completely personalize a Salesforce app to match the branding of the company.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Zbcx9nM4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/0f9ukddwqlj13ekyq9gr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Zbcx9nM4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/0f9ukddwqlj13ekyq9gr.png" alt="Salesforce Theme Customizations"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;We can literally take theme customizations for a test-drive&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You can try out this feature yourself in the context of the Pulsar eCars app by uploading the app package to a developer edition or scratch org. You can get the GitHub repo for the eCars app at the following URL and if you need a review on how to deploy a Salesforce app to a scratch org from a GitHub repo, you can refer back to the very first article I wrote on this series (link here):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/trailheadapps/ecars"&gt;https://github.com/trailheadapps/ecars&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating Custom Record Pages Without Code
&lt;/h2&gt;

&lt;p&gt;Being able to customize the theme colors, logos, and images is certainly a nice appetizer, but the main course is really when we get into the user interface components of record pages without having to use any code. Lightning Experience has really taken this to the next level as well—those of you too new to have known Classic Experience might not fully appreciate all the new features Lightning offers.&lt;/p&gt;

&lt;p&gt;For the eCars app, we get to design, from scratch, a record page for the standard Lead object.  Regardless of which object we’re working with, displaying relevant information to the user in both a logical and functional way is paramount. With the Lightning record pages, we’re presented with a plethora of variations on how we can optimize things for the user, all without code:&lt;/p&gt;

&lt;h3&gt;
  
  
  Page Templates
&lt;/h3&gt;

&lt;p&gt;How should we organize information on the page? Do we need a header and two equal regions? A header, main section, and a sidebar? No header and three columns?&lt;/p&gt;

&lt;p&gt;Even if none of the many out-of-the-box layouts work, we can create a custom page template that can be achieved with some light coding.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Fq_g9c4J--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/q2kbdz0p0j8vny7f967e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Fq_g9c4J--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/q2kbdz0p0j8vny7f967e.png" alt="Lightning Page Templates"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;If none of these options work, you could be overthinking things&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Drag-and-Drop Components
&lt;/h3&gt;

&lt;p&gt;After the page regions are defined, we can simply start building out the record page using a number of drag-and-drop components such as tabs, record details, record highlights, related list items for the sidebar, etc. Basically, we can include anything that someone interacting with the record might need to access.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zzvCoCjb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ua53qaxcyvfnziab6ywg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zzvCoCjb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ua53qaxcyvfnziab6ywg.png" alt="Out of the Box Lightning Components"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Page Activations for Different Use Cases
&lt;/h3&gt;

&lt;p&gt;Once the page has been built and defined, we also have the option of activating it as a single org-wide default, or going a few levels deeper and then defining multiple versions of the same record page for different apps, user profiles, and record types. One user may need to see more, less, or different information for the same record. This reality makes defining multiple versions a handy tool to achieve that use case.&lt;/p&gt;

&lt;p&gt;The page activations can even be as granular as desktop vs. phone for added optimization for the different form factors. &lt;/p&gt;

&lt;h2&gt;
  
  
  Even More Granular UI Elements Without Code
&lt;/h2&gt;

&lt;p&gt;In addition to the customizations of the Lightning Record Pages, there are other, more specific ways to customize without code.&lt;/p&gt;

&lt;h3&gt;
  
  
  Compact, Search, and Page Layouts
&lt;/h3&gt;

&lt;p&gt;If we need to customize which fields appear and in what order—in places like the Record Highlights component, the Global Search results, or the Record Details component— we can use drag-and-drop methods on the Compact Layouts, Search Layouts, and Page Layouts sections of the Object Manager in Setup. I use these frequently as they’re essential to organizing information for the users.&lt;/p&gt;

&lt;h3&gt;
  
  
  Dynamic Actions with Conditional Visibility
&lt;/h3&gt;

&lt;p&gt;This is a relatively new feature at the time of this writing (only a few releases old), and it’s already helped me with those client requests that go something like, “Can we hide this button until so-and-so has filled out x,y,z or the record has gotten to this stage?” I used to hack this functionality together by creating a mess of record types and different page layouts, or I’d just code a custom visualforce page. But now, hiding/rendering actions is as easy as defining the filters for them with a few clicks.&lt;/p&gt;

&lt;p&gt;The one consideration here is that this only works (currently) for desktop interfaces.&lt;/p&gt;

&lt;h3&gt;
  
  
  Dynamic Forms
&lt;/h3&gt;

&lt;p&gt;Dynamic forms take the whole “conditional visibility” thing to a new level. This feature applies not just to buttons and actions, but to individual fields. Similar to the above use-case example for hiding buttons, sometimes a record just might present too many fields to the user at once. Dynamic forms solve this by allowing you to define under which conditions certain fields should be visible. As a result, users can go on about their business of filling things out and updating records. Then, as things progress, dynamic forms hide irrelevant fields and present new, relevant ones. This creates a nice, streamlined user experience.&lt;/p&gt;

&lt;p&gt;One “gotcha” we have to keep in mind is that this is only available for custom objects, not standard ones like Leads, Accounts, Contacts, and Opportunities. That being said, I’m betting this will change soon enough.&lt;/p&gt;

&lt;h2&gt;
  
  
  Screen Flows – Multi-Step Wizards Without Code
&lt;/h2&gt;

&lt;p&gt;Screen flows are probably one of the most powerful tools we can leverage when it comes to custom user experiences without crossing into the “code zone.” If an app builder needs to hold a user’s hand during a complex and multi-step design process, then the screen flow is the likely tool of choice. I’ve found that there is a bit of a learning curve with screen flows. Although it’s hard to design them nicely from the outset, once someone gets the hang of it, they’ll need very little time to build out a totally bespoke data-entry wizard user experience during those times when even dynamic forms don't get the job done.&lt;/p&gt;

&lt;p&gt;And once Lightning Components get involved, flows can even launch and exchange information with Lightning Components in the middle of a flow. The possibilities really are endless.&lt;/p&gt;

&lt;h2&gt;
  
  
  Concluding Thoughts and Other Helpful Resources
&lt;/h2&gt;

&lt;p&gt;As I said earlier, designing front-end experiences is not one of my strong suits. I’m pretty sure that if I had not found Salesforce on my app-building journey, I probably would have quit and found a different line of work, or I would have just become a purely back-end developer.  The UI/UX tools and features on the Salesforce platform have instead helped me to deliver complete app experiences, front to back.&lt;/p&gt;

&lt;p&gt;For more information and specific practice on some of the topics covered, check out the links to the Trailhead modules and resources below:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;a href="https://trailhead.salesforce.com/content/learn/modules/lightning_app_builder"&gt;Lightning App Builder&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://trailhead.salesforce.com/content/learn/modules/lex_customization"&gt;Lightning Experience Customization&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://admin.salesforce.com/blog/2020/try-dynamic-actions-in-app-builder-with-the-summer-20-release"&gt;Try Dynamic Forms and Actions&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://trailhead.salesforce.com/en/content/learn/modules/lex_migration_customization"&gt;App Customization Lite&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://trailhead.salesforce.com/en/content/learn/trails/build-flows-with-flow-builder"&gt;Build Flows with Flow Builder&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://developer.salesforce.com/docs/atlas.en-us.lightning.meta/lightning/components_config_for_app_builder_template_component.htm"&gt;Custom Templates For App Builder&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://help.salesforce.com/articleView?id=customize_recordtype.htm&amp;amp;type=5"&gt;Creating Record Types In Salesforce&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the next article, we’re going to shift gears and dive into some actual coding for the eCars app with Lightning Web Components.&lt;/p&gt;

&lt;p&gt;If you haven’t already joined the official Chatter group for this series, I certainly recommend you do so. That way, you can get the full value of the experience and also pose questions and start discussions with the group. Oftentimes, there are valuable discussions and additional references available there, such as the slides from the presentation and links to other resources and references.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://sforce.co/34Ld7xz"&gt;https://sforce.co/34Ld7xz&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;About me:  I’m an 11x certified Salesforce professional who’s been running my own Salesforce consultancy for several years. If you’re curious about my backstory on accidentally turning into a developer and even competing on stage on a quiz show at one of the Salesforce conventions, you can read&lt;a href="http://green.salesforce.com/blog/2017/04/accidental-developer-to-dst17-finalist.html"&gt; this article&lt;/a&gt; I wrote for the Salesforce blog a few years ago.&lt;/p&gt;

</description>
      <category>salesforce</category>
      <category>heroku</category>
    </item>
    <item>
      <title>Data Modeling in Salesforce and Heroku Data Services</title>
      <dc:creator>Jason Sun</dc:creator>
      <pubDate>Sat, 05 Dec 2020 04:43:34 +0000</pubDate>
      <link>https://dev.to/jasonomnivo/data-modeling-in-salesforce-and-heroku-data-services-569e</link>
      <guid>https://dev.to/jasonomnivo/data-modeling-in-salesforce-and-heroku-data-services-569e</guid>
      <description>&lt;h2&gt;
  
  
  (Heroku and Salesforce - From Idea to App, Part 3)
&lt;/h2&gt;

&lt;p&gt;This is the third article documenting what I’ve learned from a series of &lt;a href="https://trailhead.salesforce.com/live/videos/a2r3k000001n2Ig/modern-app-development-on-salesforce/?ref=hackernoon.com"&gt;10 Trailhead Live video sessions on Modern App Development on Salesforce and Heroku&lt;/a&gt;. In these articles I’m walking you through how to combine Salesforce with &lt;a href="https://www.heroku.com"&gt;Heroku&lt;/a&gt; to build an “eCars” app—a sales and service application for a fictitious electric car company (“Pulsar”) that allows users to customize and buy cars, service techs to view live diagnostic info from the car, and more. In case you missed my first article, you can find the link to it below and start from the beginning. Otherwise, if you’re specifically looking for data modeling, you’re in the right place.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/jasonomnivo/modern-app-development-on-salesforce-and-heroku-206j"&gt;Modern App Development on Salesforce and Heroku&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/jasonomnivo/jumping-into-heroku-development-48ep"&gt;Jumping Into Heroku Development&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Just as a quick reminder: I’ve been following this Trailhead Live video series to brush up and stay current on the latest app development trends on these platforms that are key for my career and business. I’ll be sharing each step for building the app, what I’ve learned, and my thoughts from each session. These series reviews are both for my own edification as well as for others who might benefit from this content.&lt;/p&gt;

&lt;p&gt;The Trailhead Live sessions and schedule can be found here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://trailhead.salesforce.com/live"&gt;https://trailhead.salesforce.com/live&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Trailhead Live sessions I’m writing about can also be found at the links below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://trailhead.salesforce.com/live/videos/a2r3k000001n2Jj/modern-app-development-on-salesforce"&gt;https://trailhead.salesforce.com/live/videos/a2r3k000001n2Jj/modern-app-development-on-salesforce&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/playlist?list=PLgIMQe2PKPSK7myo5smEv2ZtHbnn7HyHI"&gt;https://www.youtube.com/playlist?list=PLgIMQe2PKPSK7myo5smEv2ZtHbnn7HyHI&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  On the last episode…
&lt;/h2&gt;

&lt;p&gt;Last session, we walked through Heroku buildpacks and learned how to start building on Heroku with a particular web language. The buildpacks were nicely structured, with intuitive instructions and installation steps for getting Heroku and your local machine set up to develop on one of the supported languages. We also ran through the process of using the command line, VS Code, and specific Heroku git commands to deploy a sample Lightning Web Components (LWC) app to a new Heroku app environment. Not bad for under an hour’s work!&lt;/p&gt;

&lt;p&gt;In this episode, we’re going to get into the bones of any modern application: the data layer.&lt;/p&gt;

&lt;p&gt;One of the things I find funny about data modeling is that almost everybody does it in their regular work, but rarely do people think too deeply about it (unless they’re developers or DBAs). There’s also a really steep learning curve when you graduate from a flat file like Excel to a multi-table relational database like Access. Every client I talk to can describe, to a degree, what kind of data their business needs to track. But going beyond that—initiating the right conversations with clients, reading between the lines, and teasing out the best data model of their application—is somewhat of an art form.  Data modeling also seems to be a bit of an underappreciated part of the application-building process. Speaking from experience, getting the data model right or wrong for an application can mean the difference between a smoothly performing app that generates useful, insightful data and an app that gets “spaghettified” with workarounds and code to make up for the data modeling missteps made at the outset.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ToDjLU76--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/558upeys6emb23utfba2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ToDjLU76--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/558upeys6emb23utfba2.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;A lot harder when you’re already a few million rows down the data rabbit hole!&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Data Modeling in Salesforce Using Point-and-Click Methods
&lt;/h2&gt;

&lt;p&gt;As we dive into our data modeling for the eCars app, there are two things worth noting about Salesforce’s data modeling features: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Standard Objects establish a data model right out of the gate for Salesforce applications.&lt;/li&gt;
&lt;li&gt;  Custom Objects and Custom Fields provide the ability to rapidly extend and prototype additional data requirements for any application.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;They also touch on Big Objects and External Objects, but in my experience, these rarely come into play except for enterprise-level implementations that have large data sets and external data sources. For the most part, Standard and Custom Objects covers 80% or more of the use cases in my experience.&lt;/p&gt;

&lt;p&gt;One major Salesforce data-modeling feature that requires experience and attentiveness is its attached dependencies and automatically generated metadata components. Many “freebies” and metadata dependencies come attached (i.e. conveniently created for you) to the custom objects, fields, and relationships that one creates in the system. For example, when you create custom objects and fields, the system already allows you to set and handle some things conveniently like creating a tab, default list views, page layouts, reports, and the security model down to the field level. &lt;/p&gt;

&lt;p&gt;Creating a relationship field, such as a lookup or master-detail relationship, also conveniently renders the child object (i.e. the table on the “many” side of a one-to-many relationship) as a related list on the parent object’s record page so that navigation is easy and intuitive.  Some key things to know about the two different relationship fields are below and also demonstrates the kinds of “freebies” or metadata dependencies that are generated with each type (rollups, sharing rules, etc.). &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--VomQ_nsi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/br4mql8zlo4m3z9774kx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--VomQ_nsi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/br4mql8zlo4m3z9774kx.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This all results in the ability to immediately interact with and prove out your data model in your app and make tweaks and adjustments quickly. I can’t count how many times this has come in handy when working with clients on the initial vision of their apps. Instead of having to create ERDs and work up the data model before putting pencil to paper, we can just go directly to prototyping in real-time. Plus, the Schema Builder conveniently draws out the ERD as the data model is built out. You’ll also see in the video that it’s possible to build out the data model visually directly on the Schema Builder!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--M5qvw79_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ny62ft217ur7ord936b4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--M5qvw79_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ny62ft217ur7ord936b4.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Pretty nice when the data model comes with these freebies as it’s being built out&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Building the eCars Data Model
&lt;/h2&gt;

&lt;p&gt;By using the point-and-click data modeling features of Salesforce, we should be able to build out the entire eCars data model in under 20 minutes. The screengrab from the Salesforce Schema Builder tool below shows us the different tables/objects that are part of the app, how they’re related to each other (they’re all Lookup relationships here, no Master-Detail relationships so far) and which fields are required or automatically generated upon record creation. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ZPyOpi0_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/rz4g5zykb5ugs6n0edn8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ZPyOpi0_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/rz4g5zykb5ugs6n0edn8.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A written interpretation of the data model’s relationships could be as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  A car can have zero, one, or more Configurations.&lt;/li&gt;
&lt;li&gt;  Each configuration can have zero, one, or more Car Options.&lt;/li&gt;
&lt;li&gt;  A Vehicle Order can act as a parent and/or child for a Configuration and vice versa.&lt;/li&gt;
&lt;li&gt;  A Lead can be related to zero, one, or more Configurations. (The data model implies that a Lead can be interested in multiple Configurations.)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Understanding what limitations and implications a data model conveys is one of the key skills in app development I’ve grown to appreciate.&lt;/p&gt;

&lt;h2&gt;
  
  
  Heroku Data Services
&lt;/h2&gt;

&lt;p&gt;Data modeling on Heroku, on the other hand, follows some of the more traditional tools you might expect with SQL databases. Still, there are several GUI tools to help as well, which I’ll mention later. Heroku also features several important add-ons for scalability.&lt;/p&gt;

&lt;p&gt;The four major data services we’ll focus on for the eCars app are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Heroku Postgres (primary relational database)&lt;/li&gt;
&lt;li&gt;  Heroku Redis (in-memory key-value data store)&lt;/li&gt;
&lt;li&gt;  Apache Kafka (distributed streaming platform)&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://www.heroku.com/connect"&gt;Heroku Connect&lt;/a&gt; (Connect Salesforce Data and Heroku Postgres)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s look at each of those to see how we’ll use them.&lt;/p&gt;

&lt;p&gt;For Heroku, while other 3rd-party databases are available in the Elements marketplace, the officially supported database of choice is &lt;strong&gt;&lt;a href="https://www.heroku.com/postgres"&gt;Heroku Postgres&lt;/a&gt;&lt;/strong&gt; and is appropriately the most popular Heroku add-on. Heroku, like Salesforce, allows you to create your data model on Postgres using both command-line methods such as in VS Code as well as through a UI via the Heroku application manager. I’ve also used pgAdmin to manage Postgres databases as well and have used it in conjunction with Heroku Postgres databases. I don’t know any people who purely live in the command-line when it comes to databases, but I’m willing to bet they’re pretty fast on the keys!&lt;/p&gt;

&lt;p&gt;For the eCars app, we’ll use Postgres to store our basic relational data—customer information, car information, etc.&lt;/p&gt;

&lt;p&gt;This is actually my first exposure to Redis and Kafka. However, after Julián explained the use cases for each, I can see how these are very important data services for highly scalable applications. Scalability seems to be more and more of a recurring theme for Heroku also.&lt;/p&gt;

&lt;p&gt;Modern applications have to run lightning fast as consumers have come to expect that kind of performance. And even though solid-state drives might improve performance, the reality is that on-disk databases are just not going to be as fast as in-memory data. So, to get high-volume apps running super fast, you can see why you need something like &lt;strong&gt;&lt;a href="https://www.heroku.com/redis"&gt;Heroku Redis&lt;/a&gt;&lt;/strong&gt; or Salesforce Platform Cache to store some of the higher-volume information that powers the app in fast, high-performance memory. Otherwise, the database would buckle under the number of requests.&lt;/p&gt;

&lt;p&gt;On top of that, modern applications typically run on distributed cloud infrastructure and may be using multiple data sources which need a lot of real-time throughput. In front of the data sources are a collection of services, and we need a way to reliably and quickly pass messages among them. &lt;strong&gt;&lt;a href="https://www.heroku.com/kafka/"&gt;Apache Kafka on Heroku&lt;/a&gt;&lt;/strong&gt; fits the bill for this requirement, especially in large enterprise applications. &lt;a href="https://kafka.apache.org/"&gt;Apache Kafka&lt;/a&gt; is an event-streaming platform that will allow our eCars app to potentially scale to very high loads in a distributed app architecture. It also makes sense that there isn’t a free tier for this service, as I can imagine the expense it takes just to run one Kafka cluster.&lt;/p&gt;

&lt;p&gt;Finally, &lt;strong&gt;Heroku Connect&lt;/strong&gt; allows Salesforce data to connect with Heroku Postgres in a bi-directional manner with a quick set-up. This saves us from having to do a custom integration between Salesforce and Heroku Postgres, but usually the deciding factor is the cost. Using Heroku Connect will allow us to seamlessly and easily connect Salesforce data to Heroku Postgres in a bi-directional fashion in near real-time.&lt;/p&gt;

&lt;p&gt;One thing I’d like to clarify (since it used to confuse me) is the difference between Heroku Connect and &lt;a href="https://devcenter.heroku.com/articles/heroku-external-objects"&gt;Heroku External Objects&lt;/a&gt;. While Heroku Connect works with Salesforce standard and custom objects, Heroku External Objects is strictly a uni-directional OData service, meant to allow Heroku Postgres tables to sync to Salesforce External Objects. The naming can get confusing, so it’s important to keep this nuance in mind. Heroku External Objects also comes with the Heroku Postgres add-on while Heroku Connect is a paid service.&lt;/p&gt;

&lt;h2&gt;
  
  
  Concluding Thoughts
&lt;/h2&gt;

&lt;p&gt;That’s an overview of data modeling on both Salesforce and Heroku, and how we’ll get them to work together.&lt;/p&gt;

&lt;p&gt;As I mentioned previously, I’m of the opinion that getting the data model right is probably one of the most important things when it comes to designing applications. If it goes wrong, everything can turn into a futile exercise, from the way data is collected to what the business intelligence/analytics tools produce. &lt;/p&gt;

&lt;p&gt;I got introduced to this mode of thinking pretty early on, before I even started my career. A USC Marshall Business School instructor named &lt;strong&gt;&lt;a href="https://www.linkedin.com/in/douglasshook/"&gt;Douglas Shook&lt;/a&gt;&lt;/strong&gt; taught a database class to business students like me. I still credit that class, its data-modeling lessons, and the bit of SQL it taught us, with my eventual pursuit of Salesforce as my career. We did countless homework problems and quizzes where he would give the class a bunch of receipts and a report from a shoe store or something, and then ask us to draw an ERD for a possible database system that generated them. When I reflect on that experience, I definitely have some renewed appreciation for how Salesforce and Heroku make it simple to handle the data aspects of an app now.&lt;/p&gt;

&lt;p&gt;If you want to take a deeper dive into data modeling considerations, I recommend taking a look at this article that Mohith wrote on &lt;a href="https://medium.com/salesforce-architects/data-model-design-considerations-when-building-salesforce-applications-part-1-4e605f504b54"&gt;Data Model Design Considerations When Building Salesforce Apps&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In the next article, we’re going to look at how we can customize the front-end UI components of Salesforce for our eCars app, all without writing any code.&lt;/p&gt;

&lt;p&gt;If you haven’t already joined the official Chatter group for this series, I certainly recommend you do so. That way, you can get the full value of the experience and also pose questions and start discussions with the group. Oftentimes, there are valuable discussions and additional references available there such as the slides from the presentation.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://sforce.co/34Ld7xz"&gt;https://sforce.co/34Ld7xz&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;About me:  I’m an 11x certified Salesforce professional who’s been running my own Salesforce consultancy for several years. If you’re curious about my backstory on accidentally turning into a developer and even competing on stage on a quiz show at one of the Salesforce conventions, you can read &lt;a href="http://green.salesforce.com/blog/2017/04/accidental-developer-to-dst17-finalist.html"&gt;this article&lt;/a&gt; I wrote for the Salesforce blog a few years ago.&lt;/p&gt;

</description>
      <category>salesforce</category>
      <category>heroku</category>
    </item>
    <item>
      <title>Jumping into Heroku Development</title>
      <dc:creator>Jason Sun</dc:creator>
      <pubDate>Wed, 02 Dec 2020 05:34:36 +0000</pubDate>
      <link>https://dev.to/jasonomnivo/jumping-into-heroku-development-48ep</link>
      <guid>https://dev.to/jasonomnivo/jumping-into-heroku-development-48ep</guid>
      <description>&lt;h2&gt;
  
  
  (Heroku and Salesforce - From Idea to App  Part 2)
&lt;/h2&gt;

&lt;p&gt;This is the 2&lt;sup&gt;nd&lt;/sup&gt; article documenting what I’ve learned from a series of &lt;a href="https://trailhead.salesforce.com/live/videos/a2r3k000001n2Ig/modern-app-development-on-salesforce/?ref=dev.to"&gt;10 Trailhead Live video sessions on Modern App Development on Salesforce and Heroku&lt;/a&gt;.  In these articles I’m  walking you through how to combine Salesforce with Heroku to build an “eCars” app—a sales and service application for a fictitious electric car company (“Pulsar”) that allows users to customize and buy cars, service techs to view live diagnostic info from the car, and more.  In case you missed my first article, you can find the link to it here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/jasonomnivo/modern-app-development-on-salesforce-and-heroku-206j"&gt;Modern App Development on Salesforce and Heroku&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This article is going to cover setting up &lt;a href="https://www.heroku.com"&gt;Heroku&lt;/a&gt;, installing &lt;a href="https://lwc.dev/"&gt;LWC&lt;/a&gt;, and setting up the deployment for our app.&lt;/p&gt;

&lt;p&gt;As a quick reminder, I’ve been following this series to stay current on the latest app development trends on these platforms, which are key for my career and business.  I’ll be sharing step-by-step building the app, what I’ve learned, some of the highlights, and my personal take on some of the content.&lt;/p&gt;

&lt;h2&gt;
  
  
  In the last article…
&lt;/h2&gt;

&lt;p&gt;In the last article, we walked through an overview of the Salesforce and Heroku Platforms and how they can work together.  We also did some pre-work to get set up for building the eCars app.  So, if you are jumping in at this point, here are the following prerequisites you will need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Getting a free Salesforce dev org: &lt;a href="https://developer.salesforce.com/signup"&gt;https://developer.salesforce.com/signup&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  Installing the Salesforce CLI: &lt;a href="https://developer.salesforce.com/tools/sfdxcli"&gt;https://developer.salesforce.com/tools/sfdxcli&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  Installing Git (required for Heroku CLI): &lt;a href="https://git-scm.com/book/en/v2/Getting-Started-Installing-Git"&gt;https://git-scm.com/book/en/v2/Getting-Started-Installing-Git&lt;/a&gt; (I also personally have Github Desktop.)&lt;/li&gt;
&lt;li&gt;  Installing the Heroku CLI: &lt;a href="https://devcenter.heroku.com/articles/heroku-cli"&gt;https://devcenter.heroku.com/articles/heroku-cli&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  Installing VSCode: &lt;a href="https://code.visualstudio.com/"&gt;https://code.visualstudio.com/&lt;/a&gt; (I recommend also getting the Salesforce Extension Pack after installing VSCode.)&lt;/li&gt;
&lt;li&gt;  Cloning the eCars GitHub repo: &lt;a href="https://github.com/trailheadapps/ecars"&gt;https://github.com/trailheadapps/ecars&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For this article, there is another free account to sign up to start exploring Heroku: &lt;a href="https://signup.heroku.com/"&gt;https://signup.heroku.com/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The only catch with the “Free Hobby” version of Heroku is that the dyno will automatically turn off when it’s not in use. There is also a limit of 500 hours of uptime per month on the free tier.  It seems pretty fair to me—if they’re going to offer me some free compute resources, it’s only reasonable that they turn off the lights when I’m not actively using the resources.&lt;/p&gt;

&lt;h2&gt;
  
  
  Diving into Heroku
&lt;/h2&gt;

&lt;p&gt;Let’s start with an introduction to Heroku, all the bells and whistles it comes with, and how to get quickly up to speed with deploying an app on the platform.  If you’re not familiar with Heroku, it’s a PaaS solution for quickly creating and deploying apps.  With Heroku the idea is for developers to focus on building their app, and the platform takes care of the infrastructure stuff (DevOps, scaling, environments, and so on).&lt;/p&gt;

&lt;p&gt;One of the handy things about Heroku is the Buildpacks you can select and launch right off the bat.  I’ve played around with setting up an Amazon EC2 application server from scratch.  I’m not afraid to admit that I spent a good two hours sorting through documentation and help articles just to install the right pre-requisites on the instance.  &lt;/p&gt;

&lt;p&gt;With Heroku, however, you can just pick your programming language and Heroku will quickly create a turnkey process with these Buildpacks to get going with a particular language.  &lt;/p&gt;

&lt;p&gt;Heroku has 8 main officially-supported languages: Node.js, Ruby, Python, Java, PHP, Go, Scala, and Clojure.&lt;/p&gt;

&lt;p&gt;However, there are many community Buildpacks available for other languages and frameworks as well.  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jQXATLre--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/4qw3a4rqri7y5fadgvvg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jQXATLre--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/4qw3a4rqri7y5fadgvvg.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For the eCars app we’re building, we’re using the Node.js Buildpack.  While, at the time of this writing, I certainly understand and can work my way through javascript code, I wouldn’t say I have as much depth specifically with Node.js as I have with Salesforce APEX and Visualforce code.  However, I’m looking forward to diving a little deeper into Node.js as I consider it cross-training for Salesforce aura and Lightning Web Components.&lt;/p&gt;

&lt;p&gt;Going through the Buildpack for Node.js is super simple.  The step-by-step instructions and links to required installed components are very easy to follow and I found myself up and running with Node.js in under 30 minutes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://devcenter.heroku.com/articles/getting-started-with-nodejs#set-up"&gt;https://devcenter.heroku.com/articles/getting-started-with-nodejs#set-up&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You should also install the current Long-Term Support (LTS) version of Node.js from &lt;a href="https://nodejs.org/en/"&gt;https://nodejs.org/en/&lt;/a&gt;.   At the time of this writing, the LTS version was 14.15.1.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--GqkDZjb_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/k99d8lu6pm2a76krikq9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--GqkDZjb_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/k99d8lu6pm2a76krikq9.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Turnkey process and instructions for getting started with Node.js on Heroku&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  VSCode CLI Exercises and Installing LWC
&lt;/h2&gt;

&lt;p&gt;I mentioned earlier that Node.js would be good cross-training for Lightning Web Components (LWC).  In fact, the next step is to actually install LWC using npm, which comes with Node.js installed earlier.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://lwc.dev/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After following the instructions at the link above on the VSCode command line, and answering three questions about the type of app I wanted to create, npm was quickly on its way installing all the dependencies for the LWC app.  Although I don’t understand what all the installed dependencies mean, I can appreciate all the hard work that went into making the app easy to use.&lt;/p&gt;

&lt;p&gt;After a few minutes of installation, the sample LWC app was up and running on my localhost machine on port 3001.  At this point, one could continue building and testing the app locally until ready to deploy to Heroku.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deploying the Local Sample LWC App to Heroku
&lt;/h2&gt;

&lt;p&gt;Now let’s deploy to Heroku. Deploying the app to Heroku is a simple exercise. You only need to know several git commands with some Heroku flavor attached.  Heroku is git-based so whatever you’re deploying needs to be under git source control.  The commands to then deploy are simple and should be familiar to anyone who has used git commands on a command-line interface:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;span&gt;First, create your Heroku app with desired name&lt;/span&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;heroku create [app name]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;&lt;span&gt;Second, commit Something to Git for Deployment&lt;/span&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git commit

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;&lt;span&gt;Finally, push the Source to the Main Branch on Remote Heroku Git Server to Deploy&lt;/span&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git push heroku main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are some deeper level items on this topic, such as the Procfile and package.json. These files deal with the application’s dependencies and instruct Heroku on how to build and compile the application.  For now, this is perfectly sufficient as I have moved a local application to the remote Heroku host URL to make it accessible on the web.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dynos, Scaling, and Concluding Thoughts
&lt;/h2&gt;

&lt;p&gt;The session on Heroku involved a deep dive into Heroku’s “dynos” or a  unitized computing package required to run a particular app.  Without knowing how this all works under the hood, what you need to understand is that Heroku has some easy-to-use scaling features that add scale and power to the application vertically and horizontally to guarantee a certain level of uptime even in the face of spikes in usage.  &lt;/p&gt;

&lt;p&gt;To scale horizontally, you add MORE dynos to your Heroku application.  Doing so can let Heroku route incoming requests across more running instances of your web servers, which improves performance with high traffic situations.  Adding more dynos also allows your app to process more tasks in parallel, and handle a higher volume of jobs. There are, however, some cases where scaling horizontally doesn’t help, such as bottlenecks on services and long-running requests.  Usually in these cases, the individual dynos are overloaded so parallel processing doesn’t help.&lt;/p&gt;

&lt;p&gt;On the other hand, vertical scaling refers to making each dyno more powerful individually.  Upgrading dynos to larger dyno types will provide your app with more memory and CPU resources so that the performance of the individual dynos are improved.&lt;/p&gt;

&lt;p&gt;So if you imagine a factory with machines making trinkets, you can improve throughput by adding more machines (horizontal scaling) or by making each machine run faster (vertical scaling).  &lt;/p&gt;

&lt;p&gt;When I hear stories about a website or server crashing due to a sudden influx of visitors, I often wonder what kind of infrastructure those sites are running on and whether they would have crashed if they were using Heroku.&lt;/p&gt;

&lt;p&gt;After working on the Lightning Web components (LWC) part of the app, I admit that as someone who has lived in APEX and Visualforce for many years, I am anxious about the shift towards Javascript-based aura and Lightning Web Components as it involves learning and adapting to a new framework that isn’t always my first go-to for building custom UI/UX components in Salesforce.  However, this is certainly a trend I will have to embrace since the larger developer population is composed of more people who understand and work with Javascript than those who understand APEX.  &lt;/p&gt;

&lt;p&gt;It’s smart for Salesforce to attract and teach an existing population of Javascript developers to further enrich the entire Salesforce ecosystem.  However, the silver lining to keep in mind is the number of resources there are in the ecosystem to help first-time Salesforce, APEX, and Lightning Web components users get information and training on the platform in a very short time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Next
&lt;/h2&gt;

&lt;p&gt;Ok - now we’re all setup with Heroku, LWC installed, and our deployment ready. In the next article we’re going to learn about data modeling in Salesforce, set up the data model, then explore the integration between the two platforms by connecting Heroku to the Salesforce data using Heroku Connect.&lt;/p&gt;

&lt;p&gt;If you haven’t already, consider joining &lt;a href="https://sforce.co/34Ld7xz"&gt;the official Chatter group for this series&lt;/a&gt;. It is a great opportunity to post questions and start discussions with the group.  The slides from the presentations are also posted there after each session.&lt;/p&gt;

&lt;p&gt;About me:  I’m an 11x certified Salesforce professional who’s been running my own Salesforce consultancy for several years. If you’re curious about my backstory on accidentally turning into a developer and even competing on stage on a quiz show at one of the Salesforce conventions, you can read &lt;a href="http://green.salesforce.com/blog/2017/04/accidental-developer-to-dst17-finalist.html"&gt;this article&lt;/a&gt; I wrote for the Salesforce blog a few years ago.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Link to the on-demand session recording:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=6pgwh5Vak0I&amp;amp;list=PLgIMQe2PKPSK7myo5smEv2ZtHbnn7HyHI&amp;amp;index=2"&gt;https://www.youtube.com/watch?v=6pgwh5Vak0I&lt;/a&gt;&lt;/p&gt;

</description>
      <category>heroku</category>
      <category>salesforce</category>
    </item>
  </channel>
</rss>
