Book Announcement: A Terrible Guide to Salesforce Lightning Components ✤

Hey, hi, how are ya? Now that we got that unpleasantness out of the way, allow me to introduce you to this forthcoming book.

This book aims to make you a Salesforce Development Rockstar.

(Correction: It aims to make me a rock star, because the best way to master a subject is to teach it. But if you follow along, you’ll get to be a rock star, too. By osmosis or alchemy or some other mechanism I don’t quite understand.)

At the time of this writing in 2017, Salesforce is rocking its way to the top of the technology food chain. Fortune just named them #1 on the Fortune 50 list. Developers (and admins) are in hot demand. It’s virtually impossible to be a Salesforce Developer and not have a good job at this point. Many companies are willing to hire remotely because they just can’t find local talent.

What I’m trying to say is there’s never been a better time to be a Salesforce developer, and short of being an A.I. scientist, there may be no other type of developer with the job security of a Salesforce developer.

But first, what’s Salesforce?

Salesforce is billed as the world’s leading Customer Relationship Management system. It started out as a system focused on helping sales people keep tabs on all their leads, prospects, and customers. It has now grown to be a platform where businesses can run literally all of their information systems. Instead of having one system for CRM, another for Marketing, another for Finance, etc., Salesforce opened its system as a platform on which you, yes you, can build anything you damn well please.

To make sense of this, imagine a house. A house is very nice. It has a certain number of rooms and toilets and a yard. Maybe your house has a pool. Maybe I like you a little less now. Whatever your house is like, we can agree that a house is a house. Furthermore, it would be very problematic for me to come over to your house and declare that it should be more like a shopping mall. You’d be unhappy. Your neighbours would be unhappy. And I’d have to spend a fortune to make it happen.

The point is that getting a thing to be a different thing is expensive and wasteful.

The same goes for software. It will do you no good to yell at your word processor to be a better web browser. It’s not a web browser. It’s a word browser. Very different things.

Now, imagine I’m building a new neighbourhood. I’ve built my house, and I’ve build a house for you, too. But I’ve also given you a big chunk of land on which you can build whatever you like. In short, I’ve given you a platform to extend and build upon the house I gave you. You can build anything. Build a roller coaster for all I care.

Most software is like a house. It does what its designed to do, and it doesn’t particularly like to do anything else. Salesforce, however, is like a neighbourhood. It’s a platform you can use to build whatever you like. You can extend the database as much as you like to hold any kind of data you choose. And every year they’re releasing new tools to make it easy to build crazy things.

For example, this year they’ve released Einstein, giving all us wacky Salesforce Hackers an artificial intelligence platform to build on. Salesforce is crazy like that. They just keep giving us new goodies.

What’s the deal with Lightning?

The simplest reason to use Lightning is because Salesforce wants you to use Lightning. You will always have better luck and better support using the tools they recommend. Again, being a platform, you could manage to develop with any set of technologies you like. (Literally, if your programming language of choice supports RESTful APIs, have at it.) But you should know that Salesforce is pouring millions upon millions of R&D into Lightning.

As the saying goes, go where the money is.

So what is Lightning? It’s a collection of technologies designed to make it easier for you to build upon the Salesforce platform.

A big part of Lightning is the Lightning App Builder. This tool is mainly used by administrators to click-and-drag Lightning Components onto a page or app. It’s pretty awesome and it’s a great idea to get familiar with it. But you’re not an administrator. This book isn’t for administrators. This book is for developers. It’s for hackers. It’s for you and me.

A Lightning Component is a self-contained package of files that provide some functionality. For example, I could have a component that simply says “Hey there, Willow.” Or I could have a component contain all the fields for a signup form. Or I could have a component be a complex app that allows users to create documents and edit images and play Kumbaya on their keyboards. In other words, anything you could build on the web can be built as a component. And then an administrator using Lightning App Builder can drag Kumbaya World onto their Salesforce page.

You can even embed components within other components. This is helpful when you’re building something that you think you could use elsewhere.

For example, one of the first Lightning Components I made was an address form that used the Google Places API to auto-populate the address fields. This component has been useful in many different contexts, so I’m glad my boss made me break it out as its own piece of functionality.

This was a sneak peak

I know, I called it an announcement. But surprise! If you’ve read this far you’ve actually read a sneak peak of my forthcoming book, A Terrible Guide to Salesforce Lightning Components.

There are many ways to learn about Salesforce. My book promises to be the most inappropriate way to do so.

If you’ve been so much as mildly intrigued, entertained, tickled, or offended, please sign up to my newsletter to be the first to know when it comes out. Sign up now.

To the newsletter.

Did you do it?

Salesforce: Log Into Community As User ✤

Scenario: You’ve been using Salesforce for some time and, being a progressive person, have jumped aboard the Lightning Experience train with both feet. However, there’s one feature you keep having to go back into Classic for, and it kinda drives you nuts: Log Into Community As User. It’s such a simple button, but it makes life so much easier, and you really notice it when it’s gone, don’t ya?

The solution, at least until Salesforce brings the functionality into Lightning (which I imagine they’ll do any day now), is creating a lighting component, an Apex controller, and dragging your component onto the Contact page builder.

It’s not so complicated, I promise. Create your component and apex class, and copy-and-paste the code below into the appropriate files.

LoginToCommunityAsUser.cmp

<aura:component implements="force:appHostable,flexipage:availableForAllPageTypes,force:hasRecordId" controller="LoginToCommunityAsUser_Controller">
	<aura:attribute type="String" name="MyAccountId" />
	<aura:attribute type="String" name="UserAccountId" />
	<aura:attribute type="String" name="setupId" />
	<aura:attribute type="String" name="userId" />
	<aura:attribute name="recordId" type="Id" />
	<aura:handler name="init" value="{!this}" action="{!c.doInit}"/>

	<button class="slds-button slds-button_brand slds-hide" aura:id="button" onclick="{!c.click}">Login to Community as User</button>
</aura:component>

LoginToCommunityAsUserController.js

({
	doInit : function(component, event, helper) {
		var recordId = component.get('v.recordId');
		helper.getOrgId(component).then(function(r) {
			component.set('v.MyAccountId', r);
		});
		helper.getAccountId(component).then(function(r) {
			component.set('v.UserAccountId', r);
		});
		helper.getSetupId(component).then(function(r) {
			component.set('v.setupId', r);
		});
		helper.getUserId(component).then(function(r) {
			component.set('v.userId', r);
			$A.util.removeClass(component.find('button'),'slds-hide');
		});
	},

	click : function(component, event, helper) {
		helper.loginToCommunityAsUser(component);
	}
})

LoginToCommunityAsUserHelper.js

({
	navigateToUrl : function(a) {
		"undefined" !== typeof sforce && "undefined" !== typeof sforce.one ? sforce.one.navigateToURL(a) : window.location = a
	},

	getOrgId : function(component) {
		return new Promise(function(resolve, reject) {
			var action = component.get('c.getOrgId');
			action.setCallback( this, function( response ) {
				resolve( response.getReturnValue() );
			});
			$A.enqueueAction( action );
		});
	},

	getAccountId : function(component) {
		var action = component.get('c.getAccountId'),
				recordId = component.get('v.recordId');
		return new Promise(function(resolve, reject) {
			console.log(recordId);
			action.setParams({
				"recordId" : recordId
			});
			action.setCallback( this, function( response ) {
				console.log(response);
				resolve( response.getReturnValue() );
			});
			$A.enqueueAction( action );
		});
	},

	getSetupId : function(component) {
		return new Promise(function(resolve, reject) {
			var action = component.get('c.getSetupId'),
					recordId = component.get('v.recordId');
			action.setParams({
				"recordId" : recordId
			});
			action.setCallback( this, function( response ) {
				console.log(response);
				resolve( response.getReturnValue() );
			});
			$A.enqueueAction( action );
		});
	},

	getUserId : function(component) {
		return new Promise(function(resolve, reject) {
			var action = component.get('c.getUserId'),
					recordId = component.get('v.recordId');
			action.setParams({
				"recordId" : recordId
			});
			action.setCallback( this, function( response ) {
				resolve( response.getReturnValue() );
			});
			$A.enqueueAction( action );
		});
	},

	loginToCommunityAsUser : function(component) {
		var self = this,
				MyAccountId = component.get('v.MyAccountId'),
				CustomerAccountId = component.get('v.UserAccountId'),
				setupId = component.get('v.setupId'),
				userId = component.get('v.userId');

		self.navigateToUrl('/servlet/servlet.su?oid=' + MyAccountId + '&retURL=' + UserAccountId + '&sunetworkid=' + setupId + '&sunetworkuserid=' + userId);
	}

})

LoginToCommunityAsUser_Controller.cls

public with sharing class LoginToCommunityAsUser_Controller {
	@AuraEnabled
	public static String getOrgId() {
		return UserInfo.getOrganizationId().mid(0,15);
	}

	@AuraEnabled
	public static String getAccountId(String recordId) {
		String id = [select AccountId from Contact WHERE Id =  :recordId].AccountId;
		return id;
	}

	@AuraEnabled
	public static String getSetupId(String recordId) {
		Id userId = getUserId(recordId);
		return String.valueOf([SELECT NetworkId FROM NetworkMember WHERE MemberId = :userId AND Network.Status = 'Live' LIMIT 1]).mid(26,15);
	}

	@AuraEnabled
	public static String getUserId(String recordId) {
		String accountId = [SELECT AccountId FROM Contact WHERE Id = :recordId LIMIT 1].AccountId;
		return [SELECT Id FROM User WHERE AccountId = :accountId AND ContactId = :recordId LIMIT 1].Id;
	}
}

Now, all you have to do is drag your brand new component onto your Contact page in page page builder, and you should be good to roll. May this be as useful to you as it is to me.

7 Alternatives to Google Firing Mr. James Damore ✤

A white man lost his job this week after saying something stupid and predictably controversial, and the Internet lost its shit. How could Google fire a man for speaking his mind? It’s almost as if we all forgot that for most of us in the real world (read: outside Sillicon Valley pseudo utopic mindset), saying a stupid thing is very likely to get you fired. It’s probably the #1 cause of people getting fired, followed by, I dunno, doing drugs at work? I don’t really know, because everyone I know who’s been fired (as opposed to laid off) was fired, at least in part, for saying some stupid things.

So, in the spirit of reconcialiation, here are some alternatives Google should consider for next time:

  1. Openly and publically call one of your employees a sexist misogynist, put him on unpaid leave for a bit, and then move on as if nothing happened. I’m sure no one would treat him any differently and he wouldn’t have any problems working with or reporting to females in the future.

  2. Collectively stop sitting with him at the cafeteria. It’s not technically harassment, because it’s more like an absence of attention. This could not backfire in any way.

  3. What if Alphabet started Google 2 and moved everyone who wasn’t named James Damore to the new company, along with all of its assets? It’d be like the ultimate “No Homers” club, presuming they have at least one other James Damore on staff. James would get to pretend he got one heck of a promotion, and no one would ever have to talk to him again.

  4. Put him on an all-female team of developers. Start placing bets like it was a game of Survivor.

  5. Wage total psychological warfare by modifying every search result he ever looks up to slowly convince him that he is, in fact, a woman, no matter what his past experiences have told him. Eventually the cognitive dissonance would drive him mad, and he’d leave of his own accord.

  6. Promote him to a super secret R&D lab of one. Patent everything he ever does, but never ever let any of it go into production.

  7. Change his ringtone to “Damn it Jim! You’re an engineer, not a biologist.”

Mistakes I've Made: A Biography ✤

Ever feel like a total fuck up? I have. Almost every day in fact.

More recently, here are some profoundly stupid mistakes I’ve made in my short Salesforce Development career to date:

  1. I spent 7 full business days trying to figure out how to get images to upload to the Salesforce database from a Lightning Component. I rewrote it several dozen times in different ways. When it finally seemed to sort of work, we decided to upload to AWS instead. Easier and more cost effective in the long run. D’oh!
  2. I spent nearly 2 days trying to figure out to use a component a colleague had made rather than ask for help, because I was embarassed to admit I was stuck. D’oh!
  3. I wrote a super slick component and Apex class to query the Google Places API to auto fill an address form, only to see Salesforce announce they were releasing the same thing soon. Also I might have been able to get around the need to pipe the API through an Apex class if I’d RTFM’d.
  4. I’ve programmatically written half a dozen bits of functionality that were already available as drag and drop components. Oops.
  5. I’ve publicly reached out to other developers on Twitter and Stackexchange asking for help, outing my total n00b status.
  6. I’ve written SOQL queries within for loops within SOQL queries within for loops within… you get the picture. Holy governor limits, Batman.
  7. I’ve created massive methods of spaghetti code that I could no longer follow within just hours of creating it. Refactoring is fun, kids.

What’s my point in sharing these faux-pas? Simply this: development is messy. It’s never as good as we’d like it to be. We do embarrassing stuff all the time. There’s no such thing as genius programmers. Some of us are just better at hiding our mistakes than others.

State Obsolete ✤

What follows is a bit of speculative fiction, because why not?

In the late 2010s, cryptocurrencies like Bitcoin and Euthereum were dipping their toes into mainstream economics. For years, they had been dismissed by polite society as little more than a curiosity and something that criminals used to do their business.

How foolish we were.

In the end (or perhaps I should say: in the beginning), it wasn’t Bitcoin that took over the world. Instead, we had a plethora of currencies floating in different markets for different purposes. They were mostly interchangeable. But to discuss the cryptocurrency wars is to miss the larger culture war that was taking place. It was a war that would shape the economic, political, and social spheres forever, without firing a single shot.

The shift arguably began when young people started asking to get paid in crypto instead of hard currency. It was easier for them to use and the value kept climbing, which made saving much easier. Long attacked as “deflationary”, cryptocoins were infinitely divisible but extremely limited in supply. So, a $1 in coin today would easily double to $2 in just a few short months back then.

The gold rush mentality brought hordes of people to convert their real money for digital coin. As they did so, the value of “real” currency dropped, as the demand for it decreased.

The switch to cryptocoin was messy. While early adopters made a fortune, those late to the game found their life savings evaporate. It didn’t take long for everyone to jump on board, but the losses were horrific. Like those who didn’t survive financial crashes of the past, many took their own lives.

The bigger shift, though, would come to institutions.

The first institutions to feel the crunch were the banks.

As cryptocurrencies, by their very nature, did not allow for the “creation of money”, fractional reserve banking was not a viable option in the new financial order. While those who had the means did finish paying off their existing debts, the banks was severely limited in their ability to issue loans and collect interest. As the creation of money had long been the real source of the bank industry’s wealth, their only option was to raise interest rates. It wasn’t long before rates spiraled so out of control that no one was willing to pay.

The shift for them came faster than anyone had anticipated. As people withdrew their funds to purchase the more lucrative cryptocoin, a run-on-the-banks quickly occured. It was gradual at first, but when the first few banks started to fail, people rushed to withdraw their savings. Of course, due to fractional reserve banking, there was only enough for a fraction of the people. It was a house of cards, and the unimaginable happened. The banks failed. All of them.

As the banks failed, so did the system of credit they had built.

Next came the governments. Governments the world over had always relied on two primary mechanisms to fund their existence. The first was their control over the national currency. They could always print more money, regardless of how that devalued the money already in existence. It was a form of invisible taxation, but they called it inflation and told us it was for our own good.

The second mechanism was, of course, taxation itself. Income tax, sales tax, revenue tax, property tax… the list goes on. But most of these taxes depended on the government’s ability to monitor transactions. Without the ability to reliably know how much money was exchanging hands, it was difficult for them to know how much you owed them.

Most governments tried to crack down on cryptocurrencies for this very reason, but it was too late. The genie was out of the bottle, and there was no putting it back in.

Every day, as citizens moved more and more of their finances to anonymous and untraceable cryptocoin, government revenue decreased. As revenue decreased, they turned to lendors. But lendors – both banks and nation states alike – were in the same crunch, unable to help. Ironically, they attempted to appeal to the owners of cryptocurrencies to borrow from them. But it was plain as day that any coin lent to a government was never going to get repaid, and even if it did, the interest earned wouldn’t compare to the value of simply allowing your coin to appreciate in value.

As a result, public services got slashed. First, of course, was pensions and social aid. They’d wanted to take those away for years, anyway. Gone was the social safety net, no matter how much you, as a private citizen, had paid into it.

Then, infrastructure and investments. The government can’t invest what it doesn’t have.

Privatization was inevitable. It was also unofficial and gradual.

As public services degraded, those who had the means began investing in the services they wanted. Private police forces; private roads; private hospitals. Some of these were even illegal, but the state was too weak to do anything about it.

Eventually, one by one, the governments of the world failed. They became obsolete. The services people demanded of them were fulfilled by other, private players.

Many a would-be warlord tried to take their place, but found themselves in the same boat. People simply refused to value the old forms of currency that the warlords of the past could loot and horde. From cash to gold to diamonds and other rare metals, these were of no real value, because they were so easy to steal. Instead, people kept their wealth in crypto, away from prying eyes and out of reach of would-be thieves.

There was anarchy, absolutely. But there was no real power to fill the void. Power had always relied on wealth and violence – carrot and stick – to institute itself. Without the ability to monopolize wealth, violence was of limited use. The stick alone could not rally people to a cause.

It was a cruel reality, to be sure. A world where those who had, had everything. And those who didn’t, often might as well have not existed at all.

But for many places in the world, this was nothing new. On the African continent; South America; a good portion of Asia; and a larger chunk of “the West” than anyone liked to admit, most people had always had no one they could rely on. The social safety net was a phenomenon of Western of bureaucracy, and hardly universal.

For some, the new reality was absolutely crushing. They simply couldn’t make the shift. For many, though, the shift meant they were finally free to make their own destinies. Without government, there were no borders keeping them tied to unproductive land. No one to tell them they didn’t have the right to exploit the abundance of natural resources around the world.

No one to tell them “no”.

To be continued.

Code is not your friend. ✤

Hello world, and welcome to A Terrible Good: Software Development For Fun and Profit.

If you’ve been in software development for any length of time, you’ve surely succumbed to our most terrible disease: the tendency to see all problems as solvable by code. It’s a sort of myopia. The world becomes reduced to bits and bytes; zeroes and ones; mashed together with various logic operators to produce desired results.

Don’t believe me? Try talking to a non-coder and see how long it takes for their eyes to glaze over.

So that’s the downside: the tendency to lose touch, to see everything as a system, and to think code is the solution to all problems. (Even when the problem calls for a simple hammer.)

The upshot is that you and I have a terrific opportunity to do real good in the world – so long as we can step back and see the forest for the trees.

The key, I believe, is knowing, deep down inside, that code is not our friend.

Code is like fire. Used properly, it can power civilizations. Used improperly, we’ll bury ourselves in spaghetti code until we just hit the big delete key in the sky.

To paraphrase Einstein, we need as little code as possible, but no less.