Wednesday 29 December 2021

2021 Year in Review - Part 1

London's Calling Caricatures - 1 year and zero haircuts apart

London's Calling Caricatures - 1 year and zero haircuts apart

2021 began in the UK as we spent quite a bit of 2020, in lockdown (Lockdown 3, just when you thought it was safe to go inside someone else's house again) and doing everything over videoconference, which was starting to get a bit samey. 

January

Those of us that had submitted London's Calling presentations heard back, and I was relieved to see that I'd made the cut. 

The London Salesforce Developers held two events in January - the first for the graduation of another round of Speaker Academy candidates, and the second for Apex Trigger Essentials courtesy of my fellow co-organiser Erika McEvilly. The combination of Erika and starting from the ground up with triggers clearly resonated, as we had a record 163 signups for this event. 

I made a bold, and incorrect, prediction that there wouldn't be an in person Dreamforce in 2021. I got it right that Salesforce wouldn't bring 100k+ people to San Francisco from all over the world, but got it wrong that they'd be happy with a 5k event.

February

The Spring 21 release of Salesforce went live, including an update that corrected the CPU tracking for flows - this is enforced in the Summer 22 release, so if you haven't tested with the new behaviour the clock is ticking. As as the tradition, here at BrightGen we ran our release webinar and gave everyone a chance to spend more time in front of a screen, but at least not on camera. Yay!

London's Calling ticked ever closer, and session recording got underway. In keeping with the scale of the thing I was accompanied by a member of the content team and an AV specialist to keep things on track. I have to say I still prefer the adrenaline rush of doing everything live - there's nothing like wondering if the wifi will hold up to get the heart racing. That said, from the point of view of the organisers I can see that trying to co-ordinate a ton of speakers to present live from around the would be a total nightmare.

The London Salesforce Developers were treated to a session on respecting data protection laws in Salesforce - a dry topic, but also an important one that isn't going away.

I also launched a Substack in February, which is proving invaluable for reminding me what was going on back then!

March

The wait was finally over and London's Calling was here - another chance to spend a whole day in front of a screen! As always it felt like the hardest thing to recreate online was the expo, but at least we at BrightGen had the caricatures which do translate pretty well, as you can see at the start of this post. My session was on Org Dependent Packages, which I still think are pretty awesome, especially for large enterprises with mature orgs. You can find recordings of all of the sessions on the youtube channel, and there is some great stuff there, so it's well worth a few hours digging around. 

When it's London's Calling month, we at the London Salesforce Developers try to keep our event lightweight as we feel like there's plenty of learning around already. To this end we decided to crowd-source our member's favourite Spring 21 features, which didn't get a huge take-up. To punish them, I did most of the presenting on my favourite features, which should motivate people to either get more involved or not show up in the future!

In an unexpected turn of events, the data recovery service came back from the dead, having been retired in July 2020. A fine example of listening to your customers. There were also rumours that Marc Benioff was considering stepping down and handing over to Bret Taylor. Not entirely wrong as it turned out, but not exactly correct either.

March also marked a whole year fully remote - little did I realise that there was plenty more of this to come.


Sunday 5 December 2021

JavaScript for Apex Programmers Part 2 - Methods and Functions


(for the full Gertrude Stein quote on art having no function and not being necessary, see : https://www.scottedelman.com/2012/04/26/art-has-no-function-it-is-not-necessary/)

Introduction

In the first part of this occasional series on JavaScript for Apex Programmers, we looked at my chequered history with JavaScript, then the difference between Apex and JavaScript types. In this instalment we'll look at methods and functions.

Definitions

A method is associated with an object. It's either part of an object instance (non-static) or part of the class that objects are created from (static method). A function is an independent collection of code that can be called by name from anywhere. These are often used interchangeably (by me especially!) but the difference is important when considering JavaScript and Apex.

Apex

Apex only has methods. All Apex code called by its name is either a method being invoked on an object instance (that you or the platform created) or a static method in a class.

...

Almost all Apex code.

...

Apart from triggers. 

...

Here's an account trigger with a named collection of code that I can call later in the trigger:

trigger AccountMethod on Account (before insert) 
{
    void logMessage(String message) 
    {
        System.debug('Message : ' + message);
    }
    
    logMessage('In account trigger');
}

And if I execute anonymous and insert a trigger, I see the message appear as expected:



While this might look like a function, it's actually a static method on the trigger, as I found out by changing the use to this.logMessage('In account trigger');



It's not a useful static method though, as it can't be called from outside of this trigger. I suppose it could be used to organise code in the trigger to be more readable, but code shouldn't live in triggers so you'd do far better to put it in a utility or service class.

That interesting digression over with, as far as we are concerned Apex has methods in objects or classes, and I'll proceed on that basis.

If you want to pass some Apex code to be executed by another method, you have to pass the object to the method. An example of this that we come across pretty often is scheduled Apex:

MySchedulable mySch = new MySchedulable();
String cronStr = '21 00 9 9 1 ?';
String jobID = System.schedule('My Job', cronStr, mySch);
The platform will call the execute() method on the mySch instance of the MySchedulable class that I pass to it.

 

JavaScript

JavaScript, as I find so often the case, is a lot more powerful and a lot more confusing. JavaScript has both methods and functions, but under the hood methods are functions stored as a property of an object. 

Functions are also actually object instances - every function you create is actually an instance of the Function object.  Which means they can have properties and methods like other objects. And those methods are actually functions stored as properties. And so on.

The good news is that you don't need to care about most of this when using JavaScript in Salesforce. In my experience, what you really need know is:

Functions are First Class Citizens

In JavaScript, functions can be assigned to variables:

let log=function(message) { 
                console.log(message);
        }
   
log('Hello');

Hello

passed as parameters to other functions:

let consoleLogger=function(message) {
               console.log(message);
               }
               
let log=function(logger, message) {
             logger(message);
}

log(consoleLogger, 'Message to console');

Message to console

and returned as the result of a function;

function getConsoleLogger() {
    return function(message) {
        console.log(message);
    }
}

let consoleLogger=getConsoleLogger();

consoleLogger('Message for console');

Message for console

Functions can be Anonymous

When you create callback functions in JavaScript for very simple, often one-off use, they quickly start to proliferate and become difficult to distinguish from each other. Anonymous functions are defined where they are needed/used and don't become a reusable part of the application. Using a very simplistic example, for some reason I want to process an array of numbers and multiply each entry by itself each entry. I'm going to use the map() method from the Array object, which creates a new array by executing a function I supply on every element in the source array. If I do this with named functions:

function multiply(value) {
    return value*value;
}
let numbers=[1, 2, 3, 4];
let squared=numbers.map(multiply);
console.log(squared);
[1, 4, 9, 16]

If I don't need the multiple function anywhere else, it's being exposed for no good reason, so I can replace it with an anonymous function that I define when invoking the map method:

let numbers=[2, 4, 6, 8];
let squared=numbers.map(function(value){return value * value});
console.log(squared);
[4, 16, 36, 64]

My anonymous function has no name and cannot be used anywhere else. It's also really hard to debug if you have a bunch of anonymous functions in your stack, so exercise a little caution when using them.

Arrow Functions improve on Anonymous

Especially for simple functions. Arrow functions (sometimes called fat arrow functions) give you a more succinct way to create anonymous functions.

numbers.map(function(value){return value * value});
I can lose a lot of the boilerplate text and just write:
numbers.map(value=>value*value);

Breaking this down:

  • I don't need the function keyword - I replace it with =>
  • I don't need parenthesis around my parameter, I just put it to the left of =>
    Note that if I have no parameters, or more than one, I do need parenthesis
  • I don't need the braces, as long as the code fits onto a single line
  • I don't need the return statement, again as long as the code fits onto a single line. The result of my expression on the right hand side of => is implicitly returned
Thus arrow functions can look pretty different to regular functions:
let multiply=function(value) {
    return value * value;
}

let arrowMultiply=value=>value*value;

or quite similar

let addAndLog=function(first, second) {
    let result=first + second;
    console.log('Result = ' + result);
    return result;
}

let arrowAddAndLog=(first, second)=>{
    let result=first + second;
    console.log('Result = ' + result);
    return result;
}

Arrow functions have a few gotchas too - the major one is 'this' always refers to the Window object, regardless of how you might try to change it. 

Functions have a Context

There's quite a bit to this (pun intended!) and as I mentioned in the first instalment, this isn't intended to be a JavaScript tutorial, so I can't see any point in replicating the Mozilla Developer Network content. Instead I'll just point you at it. The key thing to remember is 'this' depends on how the function is called, not where it is declared, so if you pass an object method as a callback function, when it is invoked 'this' won't refer to the original object, but whatever object is now invoking it. I'd recommend spending some time getting to grips with the context, otherwise you'll likely spend a lot more time trying to figure out why things don't work.

Related Posts

JavaScript for Apex Programmers Part 1 - Typing