wissel.net

Usability - Productivity - Business - The web - Singapore & Twins

Avoid the "Clean Code Shock" with PMD


Your new year resolution includes "Write clean Apex code". So you run PMD with a full ruleset and get shocked by the number of violations. You drop the resolution in a blink.

Don't boil the Ocean

Even a journey of a thousand miles starts with a single step, so let's break down the task into manageable chunks to divide and rule.

There are 2 dimensions you can use: Type of code and priority levels. Using them you can turn your Clean Code journey into manageable stages.

Code Types

  • Legacy code: all code that doesn't fall in any of the two other categories
  • Changed code: code that needs change due to business requirements
  • New code: new code written for new or changed functionality (applies to copy & paste too)

Priority Levels

  • 1 = security and performance, will fail build
  • 2 = bad code, will fail build
  • 3 & 4 = hard to maintain code, will generate warning
  • 5 = ugly code, will generate hint

PMD rules for code types have different priorities. A different number of tests will fail a build:

  • 11 for legacy code (all around performance and security)
  • 33 for changed code
  • 44 for new code

Read more

Posted by on 02 January 2019 | Comments (0) | categories: Apex PMD Salesforce

Pattern in your Apex Controller


A (software) design pattern is a general, reusable solution to a commonly occurring problem withing a given context. Christoper Alexander inspired the Gang of four to apply pattern to software and enumerate 23 classic software pattern.

This article discusses how to use some of them in the context of Apex controllers.

The context: Same same, but different

You are creating an application to support construction on force.com that will serve multiple countries. Part of the requirements is to compute a risk score for any given project. While ISO standards form the foundation of the assessment, each jurisdiction has some specialties that alter the logic eventually.

This is just one of the requirements, you have many more that follow the pattern Same Same - But different.

Patterns used

Besides those, you want to know Apex Enterprise Patterns. Go Trailhead and learn.


Read more

Posted by on 29 December 2018 | Comments (0) | categories: Apex Salesforce Software

Lightning Web Components (LWC) quick overview


On December 13 Salesforce announced Lightning Web Components (LWC) a new way to build components on the Salesforce platform. Here is my take.

Expanding Lightning Family

"Lightning" serves now as a family name for modern Salesforce development. LWC are the latest family members. We now have:

The linked blog entries explain the rationale, so check them out.

Same but different

The look and feel doesn't change, the way you code them does. For now SFDX, Visual Studio Code and the Salesforce Extension Pack are to goto tools for the Spring 2019 release.

The new file structure 4 instead of 8 files

Instead of up to 8 files you only need 4. For one: all JavaScript (3 files) now lives in one ES6 JS file and we don't have an auradoc or svg file for now

Co-existence

Existing Aura based components will continue to work and will even allow to contain LWC components.

LWC in Aura, but not Aura in LWC

What you can't do is putting Aura components inside LWC. So your transition to LWC is bottom-up, not top-down


Read more

Posted by on 14 December 2018 | Comments (0) | categories: Lightning Salesforce WebDevelopment

Salesforce login statistics aggregation


A recent requirement from a customer was "I'd like to analyze logins by users in Excel", despite a dashboard approach would be sufficient. With a few million records aggregating in Excel wasn't particularly appealing

Download the log

Salesforce setup allows to download the log as csv or csv.gz file. In any case you should use the later. I learned the hard way: the chunked transfer encoding might leave you with less data be processed than you expect.

The Scanner simply stopped after a few thousand entries, while the csv parser barfed with an error.

Processing

After downloading and extracting the csv I used a small Java routine (yep, I'm that old) to aggregate logins per user, capturing the count and the first/last login date as well as the country of login (with the disclaimer caveats) and the eventual community.

For reliably and robustly reading csv in Java, usually I would use a robust library, however in this case having no dependencies and using the scanner did just nicely.


Read more

Posted by on 05 December 2018 | Comments (0) | categories: Java Salesforce

Supercharge SFDX with Ui-licious


You drank the Coolaid and you are all in and really love your Scratch Orgs. Just a few things drive you crazy.

When the API doesn't expose a setting

Your application is querying the OutOfOffice objects. Unfortunately they only exist when the Chatter settings have enabled them. To my best knowledge there is no API or config setting to achieve that from the command line. So automated testing in a scratch org won't work.

Ui-licious to the rescue

Ui-licious is a UI testing service that uses JavaScript as its scripting language. This makes an easy read and edit. A script that can set the missing OOO setting is short and simple (if you agree iFrames are easy to handle). You can (almost) read it out aloud:

// URL Provided by data object from the command line
I.goTo(DATA.result.url);
I.must.see("Chatter Settings");
// To ensure we work on the iFrame we get the id
let iframeId = UI.execute("return document.getElementsByTagName('iframe')[0].getAttribute('id')");
// The iFrame loads slowly
I.wait(10);
UI.context("#" + iframeId, () => {
	I.see("Chatter is a corporate network that lets your users work together, talk to each other, and share information, all in real time.");
    I.click("Edit");
    I.must.see("Save");
    I.select("Users can set Out of Office messages");
    I.click("Save");
})

The interesting piece in the above is DATA.result.url which is an JSON object that needs to be handed over to the Ui-licious. A small command script in tandem with SFDX does the trick. The beauty here: we directly can reuse the output of an sfdx command as input for the uilicious-cli.

sfdx force:org:open -r -p lightning/setup/CollaborationSettings/home --json > local.json
uilicious-cli  run "ProjectName" "ScriptName" --dataFile local.json -u uiliciousUser -p uiliciousPassword

It probably would be part of a larger CI script, but you get the idea! You might not store the output in a file, but use bash to capture it in memory and use --dataObject instead. Full details are in the documentation.

As usual YMMV


Posted by on 27 November 2018 | Comments (1) | categories: Lightning Salesforce

Cleaning up an APEX codebase with PMD


You inherit a large code base, it is perfect, a work of beauty. Then you wake up to the ping of your PMD run completion and find multiple thousands of rule violation (and you haven't even started to assert test assertions). Here is how to fix that.

Divide and conquer

Boiling the ocean and fix all issues in one go is hardly an option. So you need to strategize. PMD gives you a hint: every rule has a priority property, where you can specify how important this rule is. The higher the number, the less important the rule. You can run PMD using the min -[somenumber] parameter which will ignore rules with a higher value.

Next step is to decide what rules constitute your priority 1 and 2 buckets. I strongly recommend to make them mandatory fixes before the next deployment, so pick the rules carefully. The candidates I suggest are around performance and security:

Priority 1

  • ApexXSSFromURLParam
  • ApexSOQLInjection
  • ApexOpenRedirect
  • ApexInsecureEndpoint
  • AvoidDmlStatementsInLoops
  • AvoidSoqlInLoops

Priority 2

  • ApexCRUDViolation
  • ApexSharingViolations

Thereafter you decide on priority 3 onwards. Strong candidates for level 3 are all the rules that ensure code is maintainable and avoid errors, like deep nesting or cyclomatic complexity (a fancy word for "messy code")


Read more

Posted by on 23 November 2018 | Comments (1) | categories: Apex PMD Salesforce

Backing up Salesforce Meta data


Clicks not code makes the Salesforce Admin a super hero, but might send jitters through the compliance and change management team's combined spines. How can you track all of these changes?

Tracking changes

Salesforce does record, when configured, changes in setup for 180 days. The format is a log that isn't actionable (e.g. rollback). An alternative to the build in function is BlueCanvas that stores meta data automatically into a git repository. It's part of their developer focused solution that also handles the deployment and rollback of source code

Downloading meta data

When you are not ready (or haven't allocated a budget yet) to fully automate this, there's a do-it-yourself alternative. A few steps:

  • Make sure you have Java8 installed
  • Deploy the Salesforce Ant Migration tool
  • Download and deploy into your path PackageBuilder.jar developer by my colleague Kim Galant
  • create a build.properties file (see below)
  • create a build.xml file (see below)
  • run the fetchSrc.sh shell command (see below)

PackageBuilder will, when called with no instructions read ALL meta data and create one or more package.xml files. Once created you can use ANT to retrieve the data.


Read more

Posted by on 08 November 2018 | Comments (0) | categories: Java Salesforce

Lightning Mini Forms


One of my favorite lightning features is the Lightning App Builder. It allows to tailor Salesforce for a given set of users, to show what they need, how they need it.

In the page editor the endless scrolling page, record details followed by related lists, we got to love, can be broken down into multiple tabs. For related lists, the OOTB controls already allow to just pick one. Placed multiple times on a page, the layout can fit a specific audience's precise need, avoiding information overload.

However there's no control to break down the record details. The OOTB record details control will faithfully reproduce the assigned page layout with all sections. Custom controls to the rescue!

Design options

There are two options to consider: where to pull design information from and how to render it. For the later you can consider lightning:recordEdit|ViewForm or lightning:recordForm. Both can be argued for.

The lightning:recordForm only needs the fields / layout options supplied and will take care of all rendering. However you are limited to one or two columns - just like page layouts.

The lightning:record[Edit|View]Form requires coding the fields, probably using an aura:iteration, but leaves you with the freedom of layout. Typically you would use a lightning:layoutItem and its size property to determine the number of columns (with 12 / size = number of columns).

To keep it simple I'll stick to the lightning:recordForm for now.

Next question: where to provision the list of fields from? When you want an universally usable mini form, you can't hardcode them, but provide them using a design property, so they can be provided in the page editor after you dragged the component onto the page.

Still you need to decide what attributes you provide:

  • List of field names
  • Name of a field set
  • Name of a section in a page layout

I'll start with the first one and relegate the other two approaches to future posts.

To make this work you will need a custom lightning component. Let's call it MiniForm. We will only need MiniForm.cmp, MiniFormController.js and MiniForm.design. No helper or Apex will be harmed.


Read more

Posted by on 06 November 2018 | Comments (0) | categories: Lightning Salesforce

My software stack


From time to time the question pops up: what's your software stack? I use cloud based tools like LucidChart, GitHub, Bitbucket and various other SDLC related tools (subject to a future post), but still quite a number of locally installed tools.

The essentials

Tools I use on, more or less, daily basis:


Read more

Posted by on 31 October 2018 | Comments (1) | categories: Software WebDevelopment

Creating a Lightning Service


When you develop in Lightning your client side architecture can benefit as much as the server from a separation of concerns. The component library is testimony to that.

Out of the box services

The Component Library features a growing number of services:

Building your own

There is more than one way to skin you cat. You can do:

  • Lightning Style
    Philippe Ozil described in detail how to use and create your own services ?lightning style'. You should check out his Server Side Actions Service that allows you cut down on boiler plate code substantially
  • JavaScript Style
    Establish a global service extending the Window object
  • ES6 Style
    Import a JavaScript module. This would need to setup Babel - not too practical for now

Extending the window object

When you extend the window object, which is the browser's top level object, the service becomes available "standalone", like alert() (which is actually window.alert()). A service could look like this:

window.demoLib = ( function() {
	let someMethod = () => {
		return 'Something'
	}

	let helloMethod = (paul) => {
		return `Hello ${paul}`;
	}

	return {someMethod, helloMethod};
}());

This will now provide you with demoLib.someMethod() returning Something and demoLib.helloMethod('World') returning "Hello World". The final step to enable such a library is to add ltng:require to your components: <ltng:require scripts="{!Resource.demoLib} afterScriptLoaded="someMethodIfRequired" /> presuming you stored your JS in resources as demoLib.js. The Aura framework will make sure that the library is loaded once only, regardless how many components define it as dependency.

What can go wrong?

There are a few caveats:

  • For hard core Apex developers: JavaScript is case sensitive
  • You need to be clearly communicating service names to other developers in your org. If someone has the idea to name a library the same as yours, things will break. Good practice is to check if your library and function is available: if (window.demoLib && window.demoLib.someMethod) {...}
  • Fat arrow functions () => {...} are not supported in legacy browsers, so you need the slightly more verbose function(){...} (beware the this keyword behaves different then).

As usual YMMV


Posted by on 19 October 2018 | Comments (0) | categories: JavaScript Lightning Salesforce