Today’s guest is Aidan Harding. He is the Technology Director for Nebula Consulting. In this episode, we’re sitting down and talking about a variety of topics. Above all, we’re discussing how Flow and Apex can start being friends and working together. 

In the episode, we also touch on Aidan’s experience with programming, his time at Salesforce, and his current job at Nebula. Listen in to learn from his expertise with Flow and Apex.

Show Highlights:

  • Aidan’s early days in the Salesforce ecosystem.
  • What his current job is like.
  • When he decided he needed to really look at Flow as a developer.
  • How Flow aligns with programming.
  • Skills that make it easier to pick up and go with Flow.
  • What Flapex is.
  • How to bring the concept of a unit test to Flow and how Apex can help with that.
  • How important naming conventions are with Flow.
  • How this has all changed Aidan’s approach to Apex.
  • What lazy evaluation is and how it applies to Apex.

Links:

Episode Transcript

Aidan Harding:

Really education and computer science was so primitive when I came into it, that when I was visiting universities, before I started my degree, the head of computer science said, “Did you study computer science at school?” And when I said, “No,” he said, “Fantastic.”

Josh Birk:

That is Aidan Harding, technology director for Nebula Consulting. I’m Josh Birk, your host for the Salesforce Developer Podcast. And here on the podcast, you’ll hear stories and insights from developers, for developers. Today, we sit down and talk with Aidan about, well, a few topics, but mostly about how Flow and Apex can start being friends and work well together. But to kick things off, we talked about his early days in the Salesforce ecosystem.

Aidan Harding:

So from university, I had another programming job, where I was working on developer tools, actually, at a hardware company. We were working on a Eclipse plugin, funnily enough. And then I got very into racing bikes, and I just dropped out of technology entirely for a couple of years. So I was racing mountain bikes, and I was teaching primary school children cycling road safety, I was coaching mountain biking, and doing all these different things. And then one evening in a hotel bar, somebody that I was taking on a ride was asking… People always do ask you, “How do you get into guiding bike rides?” And when he heard about my background, he said, “Oh, you need to talk to this friend of mine. He runs a consultancy. He might be able to use you.” And it kind of coincided with a point in my life where I needed to start earning some more money again. And I tipped my toe into Salesforce, and then grew more into it over time.

Josh Birk:

I think it’s good to hear that the salary of a Salesforce developer might be higher than competitive mountain bike racing.

Aidan Harding:

Yes.

Josh Birk:

Okay. And how would you describe your current job?

Aidan Harding:

It’s a mix of things. It’s doing some customer development work, but a big part of it as well is providing technical leadership for our development team. So, creating internal libraries, that could make everyone more efficient in what they’re doing, and try to give some sort of direction to help people to use established software patterns in the code that they’re writing in Apex, and also trying to evaluate the architectural options that we have coming out in Salesforce. So I think architecture is something that everybody working on the project contributes to. You can have an architect who lays out the vision of what the system is going to look like, but then everyone working on it is still contributing to the architecture, and they need to understand the architectural implications of the different tools that they can use within Salesforce. So if they’re going to choose to use Flow instead of Apex or something, what impact is that going to have on your architecture? And so part of my role is to look at that, communicate that internally, and help us to make all the best choices.

Josh Birk:

Nice. And that segues nicely into our topic, or topics, for today. Talking about Flow and Apex, which are kind of two extremes, but we’re also going to talk a little bit in how they overlap. But starting with Flow, when did you come to the conclusion that as a developer, you had to take a good, hard look at Flow?

Aidan Harding:

It was very much when Before-Save Flows came into the releases and also the Salesforce architects’ decision guide around using flows or triggers, that is just such an excellent document, and it answered lots of questions and it opened a lot of questions. And it really made me think, “Okay. We need to, number one, start moving away from Process Builder, and number two, really understand how far we can go with Flow, really, and how far is too far?” I suppose it’s one of the important questions, always.

Josh Birk:

Right. Right. And I think it is nice that we’re moving into a world where, we used to have Workflows, we used to have Process Builder, we used to have Flow. And now, at least from that declarative point-of-view, we have one clear direction on the tool that we’re supposed to be using.

Aidan Harding:

Yeah. Yeah. And Flow actually, it’s very close to completely replacing the need for the other two, and you can see that it will completely take over very soon, which is great.

Josh Birk:

Now, something that’s come up on the pod before is how Flow aligns with programming. It’s framed in a lot of different ways. I just use the term declarative, some people say no-code, some people say low code. I’ve heard it described as visual code. How would you describe it?

Aidan Harding:

I think visual code is probably quite a good term for it. And one of the things I really wanted to understand when I investigate Flow is if you’re going to take it seriously as a programming tool with a visual interface, then all the power that it has has to come with the responsibility of being well-behaved as a coding tool. So sometimes I see people talking about an advantage of Flow being that you can deploy a Flow to production, and then if you need to tweak its behavior, you can just change it in production. If you swap out Flow for Apex in that phrase, people would think you’re insane. And I think Flow needs to be treated with the same respect.

Josh Birk:

Right. Right. And do you feel like the similarities… So first of all, that’s an excellent point, that some of the things that programmers do in order to keep themselves sane, keep their projects sane, clearly an overlap between Flow and Apex. Do you feel like the skills as a programmer, that actually makes it easier to pick up and go with Flow?

Aidan Harding:

I think it does. Yeah. And certainly, there are basic things that visually or in typed out code, we understand the concepts of loops, and branching, and so on, and so on. But also, we have in the back of our minds, as you say, the tricks and techniques that our programmer would use to manage the complexity of what they’re trying to do and prevent themselves from making mistakes. And we have an instinct to try to find the ways to do that within Flow, however we’re going to get to that goal.

Josh Birk:

Now, you have a blog post on using Flow, which by the way, you did not lie. I believe you described it to me as epic. It is impressively long. In the middle of it you talk about, and I have no idea how to pronounce this correctly, Flapex? What am I saying here?

Aidan Harding:

I think we were calling it Flapex. I think some other people came up with the same idea and called it Flowpex. But the idea is that because Flow allows you to write Apex actions and drop those into your Flow, where there are gaps in functionality where the Flow team just haven’t added a certain thing yet, you can bridge that gap with Apex potentially. Or if there are other things that are just concepts that you are keen on bringing into Flow, but don’t exist, you can write those yourself. So it’s allowing Flow and Apex to work together to make a bigger, kind of larger product. And I think in my mind, and it may have been a misunderstanding in my mind, I suppose, the pitch for Flow that I got before was that it was partially going to be an Apex developer and a Flow developer working together.

Aidan Harding:

And maybe the Flow person says, I need you to write this piece for me in Apex and they’ll give the Apex developer a very specific job of, “I need you to write a component that creates this task and loads the thing from here and does all this stuff. And then that’s what I want you to make for me.” And that never really appealed to me very much as an idea because the two developers, they’re not really working as a team there, it’s just one person telling the other person what to do. And the Apex developer is just endlessly churning out these points solutions for each individual thing that the Flow developer needs. And the idea behind what I was talking about with Flapex was that the Apex that we add there is about extending the reach or the expressiveness of Flow in a general way so that you build a smaller set of components there that could be used in lots of Flows and aren’t related to any specific task.

Josh Birk:

So, kind of more of a bottom up approach, not a discrete solution for a singular Flow, but more like what are some utilitarian libraries that Apex can have a positive effect on Flow in general?

Aidan Harding:

Exactly. So lots of these come to mind as an Apex developer becoming into Flow. There are concepts that you have in your mind, a very obvious one is we have maps in Apex, but Flow doesn’t really have maps, and it’s a tribute to Flow that a lot of the time in a Flow, you don’t need a map because Flows are kind of bulkified by themselves. You write a Flow in terms of a single record, but it’s going to be executed across a whole range of records, and most of the time that you use a map in Apex it’s because you’re doing something related to bulkification. So actually a lot of the uses of maps are removed to just by Flow being a good tool. But if you do actually need a map, then currently that doesn’t exist in Flow and that’s an obvious thing that you can address with this Flapex idea. You can build an Apex action that manages that map for you, and suddenly now you can write more expressive Flow.

Josh Birk:

Got it. And I want to highlight something that you just said there, and it’s something you highlight in the blog post. That as an Apex developer, you pointed out a scenario where you have SOQL in a loop, which every Apex developer has a chill down their spine when they hear that. But how does Flow smooth out that scenario so that Apex developers don’t have to worry about it?

Aidan Harding:

It was one of the first things that I bumped to when I started with Flow is that I was trying to write Flow exactly the same way as I would write normal Apex. Okay. I must be working on a list of records in a trigger context, so I’m going to need a loop, but actually Flow doesn’t present it to you like that. Flow presents you as if you’re already in the body of a loop over a set of trigger records. But when you do a query, it’s querying across the whole trigger context for you and the whole bulk locations just sourced out automatically for you. I’m not sure I explained that very well.

Josh Birk:

No, I think that makes sense. And I think that also segues that you’re hinting towards when a library, as you mentioned, is the SObjectIndex, which I believe helps with mapping. Can you give me a little bit more details about that library?

Aidan Harding:

Yeah. So SObjectIndex is something that I wrote a long time ago in Apex, I think a year or two into working on Salesforce. I found so many of the triggers that you write are doing such similar things, and one of the common cases was that you have a list of SObject records, take contacts, and you want to put them into a map, which is not indexed by the contact ID, it’s indexed by some other field on the contact. So, suppose you want to index them by the account. Now we know that it’s possible that one account might have multiple contacts. So you don’t have a list of, sorry. You don’t have a map of account ID to contact, you have a map of account ID to list of contacts. And the same sort of 20 or so lines of code to build up this map exists in so many different triggers that eventually I wanted to try and pull out the general concept of what’s going on there. And the class that I pulled that out into is this SObjectIndex. So you can create an SObjectIndex, pass in a field that you want to index your records on, and then start putting SObjects into it. And it will manage putting those into lists, indexed on whatever field you passed into it.

Josh Birk:

Got it. How can a library like that help Flow be more performant?

Aidan Harding:

If I’d queried some records in a Flow, and I need to match some of those to other records within the Flow, then my only option is to loop over the list of records that I queried and figure out when they match the things that I’m interested in. And so in terms of Apex unit, immediately recognize that that’s an example of how a map ought to work. So if we can have in a SObjectIndex and Flow, we can query some records, put them into the SObjectIndex, and then rather than having to loop over them, we just run an Apex action to say, give me the record that corresponds to this key.

Josh Birk:

Just get me the results. So I think that puts an interesting notch in the spectrum. So there’s clearly things Flow can’t do, which Apex can come in and assist with, but it also is, I’m visualizing that Flow loop right now, it feels like that there’s things that Apex would just be faster and easier and you can have a simpler and easier to read Flow if you just kind of shunt Apex in from time to time. Does that seem like a reasonable use case?

Aidan Harding:

Yeah, that’s exactly it. And we see a parallel when we’re working in a language like Apex. You can say some things of syntactic sugar, like the safe navigation operator. You could clearly do the Apex safe navigation operator. You could always get that functionality, but by having a specific operator that does that for you, it makes it easier to see what it is you’re trying to achieve because you’re working at a higher level of abstraction. So you’re focusing on what you’re trying to do, not cluttering it with unrelated things.

Josh Birk:

Right, right. Again, just sort of collapsing it down to the result itself. Yeah. And again, syntactic sugar is definitely going to be the name of my upcoming K-Pop band. Now you also present an interesting use case that I don’t think people think about a lot when it comes to Flow. You’re saying as programmers, we don’t want to deploy things to production double plus good. But also the concept of using Flow to test Flow, to kind of bring the concept of a unit test to Flow. Tell me how you think that should work and how Apex can help out with that.

Aidan Harding:

Yeah. So my, my thinking along that is that unit tests are good. I think that’s quite important. They save us so many times. They save us from making silly mistakes, they allow us to catch things when the system changes. We wouldn’t want to be without them. And as it stands there’s a really good way of running unit tests on Salesforce, which is the Apex unit test. It has all the things that you want. It’s isolated from the real data, it’s fast, but there is no equivalent thing in Flow, and we can’t really expect a Flow developer to start writing Apex just for their tests otherwise, they may as well use Apex to write the Flow itself. So what I tried to do, and I found you could do, is that because you can invoke a Flow from Apex, you can evoke a Flow from an Apex unit test. And when you do that, the Flow that you’re invoking there is running against an isolated database with only the test data you’ve put into it. So it allows you to write a test individual coding paradigm that you’re used to, but have it run with the same properties as an Apex test. And that seems really powerful.

Aidan Harding:

There are some caveats around that you need a group of Apex actions to actually make that happen in a sort of nice way. So there are obvious Apex actions, like you can very simply write an action to replicate the assertion functionality. So you write a Flow to create some test data, you make the thing happen that should run the other Flow that your testing, and then you run some Apex actions to assert that we’ve got the expected result. That part’s very easy. The construction of test data part is actually quite complicated and nuanced, but the good thing is that mature Apex development groups will have their own test factories to build test data already. And you can use Apex actions again to hook those test data factories into your Flow. So the first part of your test Flow is, call my Apex test factory to create some records, and then I can manipulate them a bit in the middle part of the Flow, and then I can call some assertions at end of the Flow and the whole thing works.

Josh Birk:

Which I think, again, I liked the overall theme here, which is, best practices within Apex are best practices that you can then bring to Flow. Things like using a test factory and organizing your unit tests in a structured way.

Aidan Harding:

Yeah, absolutely. I would say that with this whole thing, I’m not recommending that anyone on our team goes out and writes a whole load a Flow tests like this. That aspect of it was more a kind of proof of concept, and a hope that some people in the Flow teams at Salesforce may take this on and make it easier to manage. And I know that the team behind Flow are looking at testing in various different ways to try and address these sorts of things.

Josh Birk:

Got it. And is that just because of the overhead of the additional cruft that you’re adding to the org isn’t necessarily worth the payoff?

Aidan Harding:

The thing is that you would end up with so many tests that when you look at your list of Flows, most of them would be tests because when we write an Apex test class in might have 10 or 15 test methods in it, and each one of those would have to be its own separate Flow. So, I think there probably is some work that has to be done on the Salesforce side to make all of that come across really nicely. But at least what I did with the proof of concept shows that it’s… The functionalities are all kind of there, it’s so close to working, but this is a way that they could proceed.

Josh Birk:

Got it, got it. And kind of sticking with that best practices theme, how important is naming conventions when it comes to Flow itself?

Aidan Harding:

I think it’s as important as it is in code. There’s a old advert in the UK, which will mean nothing to the rest of the world, for a product called Hammerite, where a guy used to slam it on the table and say, “It does exactly what it says on the tin.” And it was a wood stain. And British developers will kind of have this concept of classes and methods. It should be like, Hammerite, you should read the name and you should be able to know exactly what’s going to be happening on the inside without having to open it. And that applies to Flow as much as it does to Apex, possibly more. Because when you look at a Flow, there are the blocks that you see on the visual thing. But there are also the variables that are kind of hidden behind a different tab as well, because things are split like that, naming becomes really important so that you know which things match up.

Josh Birk:

Got it. And going through all of this exercise, how… I’m trying to think of the best way to ask this. How has it changed your approach to Apex, and maybe, how are you navigating knowing this is a section of code that actually I could put into a Flow.

Aidan Harding:

I think that the decision guide has a really good point to make about this, which is that part of the decision about whether to use Flow or Apex actually comes down to what people you have in your team. If you already have a group of Apex developers and you have a mature deployment process, you might as well just use Apex. If that’s what you’re familiar with, and that’s what your team are good with, then Apex is really good. Flow comes into its own, where you have to hand over ownership of stuff, potentially, to people who don’t have the Apex skills. So working at a consulting company, sometimes that’s a really good argument that we can create the Flow, and the customer can own it and understand it, hopefully not change it in production.

Josh Birk:

Got it. Yeah. I mean, they’ll have the power, you can’t take it away, but agreed. I’m getting a sense of déjà vu right now. I feel like, I used to do workshops and talks about Lightning web components when we first started rolling out Aura, and I had a lot of people that were like, “Do I need to remove all my Visualforce? Do I need to port all this stuff to all of this new thing?” And it’s like, don’t panic and learn Lightning. Right? You don’t have to change your what you have currently cooking, but you should have this tool in your back pocket for the next Greenfield project that you do, the next time you do a new exercise, and then you can start properly evaluating between the two. Does that seem about right?

Aidan Harding:

Yeah, I think that is right. And there is also one very strong case to bring Flow in, which is converting old Process Builder and Workflow. The efficiency benefits of Before-Save Flow compared to a Workflow or a Process Builder that writes back to the same record that started the transaction, it’s just a massive benefit. And it’s an absolute no-brainer to switch it to Before-Save Flow, if that’s possible.

Josh Birk:

That’s interesting. I have not gone through that exercise, but I would kind of guess the similarities between Process Builder and Flow would not make that a terrible task.

Aidan Harding:

Yeah. I think there is a lot of low-hanging fruit there for just straight up converting those things.

Josh Birk:

Got it. Okay. So switching a little bit more to just Apex itself. Tell me a little bit about lazy evaluating.

Aidan Harding:

So this was something that I watched an interesting video about lazy evaluation, and just tried to see if I could apply this to Apex out of curiosity. And to explain what it actually is and what it’s about, it’s probably best to think of it in terms of either the Streams library in Java, or the list methods that you have available to you in JavaScript. So it’s working on lists of data in a very concise way. So it’s the filter, and map, and reduce methods, and that whole kind of family of things for working on lists at a kind of more abstract level. And so let’s talk about how that can be done and how that can be done efficiently. So it’s kind of an interesting aside that JavaScript doesn’t do these things in a terribly efficient way if you have a list of records.

Aidan Harding:

If you have a list of records in JavaScript and you call filter on them, what it turns at that stage is a list of records filtering out the ones that you didn’t want. And then if you call them up on it, it returns another list. And so each time you call one of these methods to change your list, it’s going through that entire list, applying the thing that you want and returning another list. So you’ve got a chain of iterations over the entire list. So it doesn’t actually end up being a very efficient thing. Although, it looks very nice. It’s a nice piece of syntactic sugar. It’s one of the most dangerous pieces of syntactic sugar in that it makes inefficient things look tidy. And so I wanted to try and get some of that sort of syntactic nicety into Apex, initially, just to see if I could, but also I wanted to preserve the efficiency so that if you chain filter, and map, all these things, it processes one record at a time. It does all of them in one iteration and it collects together all of your transformations into one thing.

Josh Birk:

Got it. And so I think you just answered this to a certain extent in the fact that you have cleaner, friendlier code, but what are some of the other advantages that this has over the grand old for-loop?

Aidan Harding:

I think once I realized that it was actually possible to build a library like this in Apex, I had a solution. I had to try and find a problem in a way. But there is a genuine problem which comes back to one of the things that I was saying before, that a lot of triggers feature the same sort of shape of code. You’re doing the same thing over and over. And your stereotypical trigger, you loop over the trigger context, you pick out some records that have changed in a way that’s interesting to you, maybe pull a single field from all of those records, you do a query, you mute it, you change the records and the result of that query, and then you do an update. And that’s such a kind of boiler plate thing that you can keep knocking out triggers that look like that forever. But if you can pick out some of the general concepts of what’s going on there, and you can use a library like the lazy iterator one that I’ve written to pull things out, then you can write it much more concisely. And also it could give you some guidance on how to break up the code that you have.

Josh Birk:

Yeah, you’re giving me flashbacks. I think you just described roughly 60% of all the code I’ve ever written in Apex. And I’m just thinking of all the triggers that I’ve written that I would describe to somebody as like, well, I stacked a bunch of maps in the beginning, I filled them, and then I beat them up until they did what I wanted. And I can actually kind of see how the lines of code would be simpler with the syntactic sugar. Awesome. Well, so for these libraries and this code that you’ve written, where can people find some of this stuff?

Aidan Harding:

So we’ve open-sourced the library that includes that lazy iterator functionality, which we have on a Bitbucket repo. We can have a link to that in the show notes. That is MIT open source, so you’re welcome to grab it, modify it. I wouldn’t say it’s enormously well-documented at the moment, but as much as anything else, something that I’m interested in is raising interesting conversations amongst the Apex developer community. So even if you read some of that stuff and think, huh, that’s interesting. I’m going to write my own spin on it. As far as I’m concerned, that’s still a good outcome.

Josh Birk:

Nice, nice. And we will definitely have links to all of this in the show notes. And so I only have one final question, and I think I might have a hint, but what is your favorite non-technical hobby?

Aidan Harding:

You think I’m going to say mountain biking, don’t you?

Josh Birk:

I do. I really do.

Aidan Harding:

It’s actually not anymore. So, these days, I like to go running more. It’s a lot easier to do in terms of time, and it’s just so simple. It gets you completely away from technology and stuff. And where I live in Devon, there’s beautiful coastlines and moorland to go running in and just kind of lose yourself. It’s fantastic.

Josh Birk:

And that’s our show. I want to thank Aidan for the great conversation and information. Of course, check out the show notes. If you want to have links to his GitHub repo, which has access to all of those wonderful projects. Thank you again for listening. And if you want to learn more about the show, head on over to developer.salesforce.com/podcast, where you can hear old episodes, see the show notes, and have links to your favorite podcast service. Thanks again. And I’ll talk to you next week.

Get notified of new episodes with the new Salesforce Developers Slack app.