Trapdoor In The Sun

Alan Shanahan, Technician & Consultant


1 Comment

Professional Online Meeting Etiquette – Six Tips

Many IT consultants find themselves using the full range or remote working tools. Of those, online conference tools can be the most useful and the most difficult to use correctly. Once you have solved the problems of scheduling through multiple time zones, giving your meeting attendees easy access and managing effective online meetings, it gets easier.

Problems still exist because people fill the meeting spaces. And people have different habits, viewpoints, idiosyncrasies and come from many cultures. Self-awareness is important.

Here are some things to consider during online meetings:

Pay Attention:
If you participate in an online meeting, be present. Don’t multi-task, because there is no such thing. You don’t want to be embarrassed when you are asked to comment on a topic you should have been listening to. We’ve all been there, and there’s no replay button.

Be A Mute Master:
Mastering control over your Mute button, whether it be on your phone or computer, is one of the most important skills you will use. All too often, I’ve heard coughs, burps, slurping, sighing and heavy breathing, sneezes, background scratching, office hubbub, yawning, traffic, babies and children, keyboard hammering (also known as typing) and a multitude of other distracting sounds. Refuse to be part of the problem by embracing your inner silence when it’s needed.

But be ready to toggle the mute button instantly when it’s your turn to speak.

Avoid Causing Echo (Feedback):
Audio feedback, digital echo, whatever you call it, it’s one of the most off-putting things that can happen during an online meeting; it can appear unprofessional and waste everyone’s valuable time. Typically it is caused by someone using audio speakers (rather than a telephone’s handset speaker or a headset or in-ear buds). Quite often, the person causing the problem is unaware of it because it does not manifest itself at their end of the connection.

Scenario:

  • Person X and Person Y join the call.
  • X is using in-ear speaker buds with the microphone on the cable.
  • Y is using the laptop’s internal speakers and microphone. The speaker volume is loud.

Sequence:

  • Person X speaks and their voice is loud over Y’s speakers.
  • The sound is so loud it repeats back into Y’s microphone and X hears their voice back (with a small delay).
  • Person Y is unaware of the problem because they can only hear the laptop speakers at their end.

Solutions:

  • Person Y lowers the speaker volume (this may reduce but not eliminate the problem).
  • Person Y uses a headset or in-ear speaker buds with cable microphone.

Be Audible & Clear:

If you find that connecting to the meeting audio through your computer (know as “VOIP” or Voice Over IP) results in a bad audio signal quality, find an alternative means of connecting e.g. dialling in through a telephone number or by improving your audio equipment or internet connection. Most online meeting systems provide a method of testing your audio signal by recording you and playing it back. Do this in advance to verify you’re not part of the problem.

Manage Audio Delays:
In many cases, particularly when calls span large geographical distance (and due to other factors) the audio signal from any one of the callers may be subject to delays. When this happens, it adds a new level of difficulty to the meeting. When you notice people taking longer than usual to respond to questions, this is often an indicator.

If delays exist in a meeting and you are in a position whereby you can address all attendees and set the scene, it’s often useful to point out to others that delays are happening on the call and ask them to take this into account. Give everyone talking a chance to complete what they are saying. Ask the attendees to be specific to whom they address their questions to avoid ambiguity. Show patience in allowing attendees to respond to questions and to progress the discussion.

The reality is that this is a tough one – there’s no hard-and-fast fix. But awareness of the problem is important, and if everyone is patient and aware, the path can be a lot smoother.

Don’t Interrupt:
One sign of an experienced or unprofessional consultant is premature interruption. Particularly when dealing with customers, allow them to finish what they are saying, even if you are champing at the bit to put them straight on something, to question something they said or to offer them your comfort with your great answer to their questions or concerns. Let them know you’ve heard them and want to hear all they have to say.

 


1 Comment

Force.com Apex Test Assertions: It Must Be a Real Test

In the course of building automated tests, it’s always good practice to pepper your test code with Assert statements to ensure your code is functioning as you would expect throughout. But, as I’ve seen more than one example of the specific behaviour in the first code section below, I think it’s something I should point out.

On first glance, it looks like the assertion is doing the right thing. But if you think about it, it’s not a real test. It only tests that the in-memory variable testAcc.Name has the value originally assigned to it a couple of lines back.

// Example 1. An in-memory-based test
Account testAcc = new Account();
testAcc.Name = 'Testing 123';
insert testAcc;

System.assertEquals('Testing123',testAcc.Name);

What it really needs to do, so that it becomes a “real” test is for the test method to query the database record just inserted and to retrieve the Name value from the record, then check it against the expected value, as shown below.

// Example 2. A database-based test
Account testAcc = new Account();
testAcc.Name = 'Testing 123';
insert testAcc;

Account checkAcc = [SELECT Name FROM Account WHERE Id = :testAcc.Id];
System.assertEquals(checkAcc.Name,testAcc.Name);

This example is, perhaps, not a great real-world scenario but I feel it illustrates the problem well.

Happy coding, if it’s your thing.


Leave a comment

What Does OOTB Mean?

Some advice along the lines of Caveat Emptor.

You’ll all have heard the words “Out Of The Box” used. This is a well-trodden phrase in the software world; a phrase meant to indicate the suitability of a product with no customisation and little or no configuration. It seems to have replaced the “as standard” stock descriptor of old.

But when you’re in the market for a software product (or suite thereof) be careful that you don’t absorb this catchphrase without due consideration to its meaning. Like so many words and phrases in our language, the context is all-important. Some examples:

Context 1: “our product manages employee data out of the box” – non-specific
Context 2: “out of the box, this product provides the ability to record employee status values A, B, C, D, E and F” – specific

In the first example, a blanket, non-specific, statement is made. It needs further examination. Be dogged in pursuit of detail. In the second example, no extraordinary claims have been made. You can still pursue some more detail to understand it a little better.

What needs to happen is a proper comparison between precisely what you need against what the precise product capabilities are. Otherwise known as a product gap analysis. In other words it’s what you need from a product compared to what that product can do.

If you ask “can your product integrate with SuperSoftware” and the answer contains the phrase “out of the box” (perhaps with a “yes” thrown in) then you need to (a) be a little wary that salesmanship is in play and (b) ask some more searching questions. What exactly do you mean by “integrate”? What SuperSoftware products are you referring to? What do you need/expect the product to do? It’s simply too general.

That’s my point made. Let’s be careful out there.


Leave a comment

Help, The Internet Isn’t Working

Please Help Me

“The internet is not working.”
“My computer isn’t working.”
“That program doesn’t work properly.”.

If you’re asking someone for help and you think this is useful information, then you really need to try harder. Most of those who have spent time supporting others will have heard lines similar to these at least once. It’s the equivalent of someone throwing their arms in the air and say “I don’t care how you do it, just fix it”, and it’s hard to take. This is bad enough when it comes from self-confessed, even proud, Luddites. But when it comes from other technicians, it is hard to forgive.

Often it’s because they have no experience of supporting users themselves and cannot perceive of the viewpoint of the person coming to their rescue. It screams loudly “I am not prepared to invest a moment into this, I just want it to work”, and much of technology just isn’t like that. If it’s man-made, it’s fallible and things go wrong.

Consider the first phrase above: “the internet is not working”. Apart from displaying a high degree of ignorance, it isn’t helpful in the slightest. You can glean from that phrase that someone has a problem browsing the web. Because the “web” and the “internet” are the same thing, right? There’s the first problem. Let’s assume there’s a problem browsing the web; how does the problem manifest itself? Is the web page slow to load? Does it load at all? Is there a visible error message anywhere? Before wasting your support person’s time, look closely at the problem. If the web browser says “HTTP error 404”, pass on that information. What web page are you trying to access? Pass that information along. What web browser are you using, Internet Explorer, Chrome, Firefox? Tell the man! It’s all useful information. Are you able to access another web page, one you know works, e.g. http://www.bbc.co.uk? Let him know. Is your WiFi connection active? Can you access any other internet services, e.g. email? Can you send messages? Can you receive? This is all useful information and accelerates your support person’s ability to resolve your problem.

Where To Start

From the support point of view, it’s all about having a decent starting point. A succinct, clear description of the problem, some supporting information. From there, it’s a game of elimination. There are many components in this problem; the technician has to think about “the chain”. What is the chain?

Computer -> browser/email client -> firewall -> wifi, if any -> cables, if any -> router -> incoming cabling -> ISP -> DNS servers -> web server

This is a simplified chain to make the point. Look at any one of those points of failure and think about how many possible faults there are. The number is quite large. It needs to be reduced. Giving additional information like “I cannot access my email” or “I can see the BBC news web site but site X pages aren’t loading” is very useful. It shows that the computer, browser, connection, router, incoming cables, ISP and DNS servers are all working and that the problem may lie at the web server side or email server of things. The techie asks “what URL did you type”, “how are you trying to access the web site” or “show me your POP3/SMTP settings” and discovers that the user has typed in the wrong URL or has a misconfigured email client. Without this extra detail, the user has to check each component above until he discovers the point of failure. Each link in the chain could force many questions and take a lot of time.

Summary

The central message of this post is not just for users of technology, it’s for designers too, at all levels. Give users the visibility they need to help you to help them. Consider how they have visibility of your system and how they can extract useful information from it to help you support them. Everyone stands to gain from this.


Leave a comment

Force.com: Visualforce; slightly better field declarations

Soft coded = good. Hard coded = bad. That’s difficult to argue against and I doubt there’s much dissent in any programming community.

Define it once, use it many times; this is part of the reusability principle that applies to code segments and text literals. When you define an input field in a Visualforce page, more often than not it is based on a field that exists somewhere in the database. It makes a whole lot of sense to take as many attributes from the original field definition as possible, so below are some examples of how you might do that.

(1) When defining a field on a page, prefix it with its label. Use this syntax:
$ObjectType.ObjectName__c.Fields.FieldName__c.Label
…where ObjectName__c and FieldName__c should be replaced as appropriate.

(2) Use the field’s own help text by referring to the InlineHelpText attribute, as shown below in this syntax:
$ObjectType.ObjectName__c.Fields.FieldName__c.InlineHelpText
…where ObjectName__c and FieldName__c should be replaced as appropriate.

(3) Limit the field length in HTML during data entry by using this syntax:
$ObjectType.ObjectName__c.Fields.FieldName__c.Length
…where ObjectName__c and FieldName__c should be replaced as appropriate.

<apex:pageBlock id="searchPageBlock">

	<apex:pageBlockSection columns="2"
	 id="searchPageBlockSection" title="Global Search" collapsible="false">

		<apex:pageBlockSectionItem id="searchAirport"
		 helpText="{!$ObjectType.Airport__c.Fields.Airport_Name__c.InlineHelpText}">

			<apex:outputLabel
			 value="{!$ObjectType.Airport__c.Fields.Airport_Name__c.Label}" />
			<apex:inputText
			 value="{!wrkAirportName}"
			 tabIndex="2"
			 id="inpAirportName"
			 maxlength="{!$ObjectType.Airport__c.Fields.Airport_Name__c.Length}"
			 onkeypress="return noenter(event);" />

		</apex:pageBlockSectionItem>
	</apex:pageBlockSection>
</apex:pageBlock>

The above code works well for text input fields. If you need information on numeric or other input field types check out the $ObjectType schema information page.


4 Comments

JustCloud.com – A Comedy Lesson

An online purchase I made towards the end of last year back put me in mind of an episode of The Office (US) where the Michael Scott Paper Company realised that it was selling paper at unsustainable prices; Michael himself rang a customer to ask them to pay more. The goods had already been paid for and delivered.

After much soul searching and consideration, I have decided to publish details of this episode.

For ages I had been searching for a reasonably-priced way to safely store my large personal photo and video collection in a cloud-based, secure location to protect me from the usual fears: fire, flood, damage, theft, hacker sabotage, pestilence and plague. I stumbled across JustCloud.com, and this seemed to provide the solution I needed, and the special offer seemed to be great value.

After two weeks of uploading my >500GB collection, I was a little happier that I was covered. I paid up front for 2 years so I got Unlimited storage for EUR 166.85. UNLIMITED. Their word, not mine.

JustCloud.com Backup External Drives

A few weeks later I was looking at application screens telling me I had to upgrade to keep the same service I was already using and had paid for. So I looked carefully at this in order to understand why; the three USB hard drives I kept permanently connected to my machine were the reason – suddenly, JustCloud decided I had to pay more for backing them up. But they decided this unilaterally and without warning. The amount they were demanding (also by email, by the way) was EUR 239.85 – far in excess of my original two year payment, and this was on top of my original payment.

I don’t need to tell you how or why this is wrong, and why I then demanded my money back, in full, without delay. I would have gladly have taken them to court for breach of contract for their nefarious practices, were it not for the complex, costly and time-consuming aspects of legal jurisdiction. I live in Ireland, they are based in the UK. But I would have dearly loved to have taught them a lesson.

Here is a snapshot of my initial angry email, sent in response to first discovering their trickery:

Message: Support,
Having signed up to JustCloud and having used it since around August 10th,
I now find that it is asking me for an additional EUR79.95 per external
drives. Drives that it has been backing up since the start of my subscription.
This is absolutely outrageous. You cannot change the terms of business part-way
into my subscription. Unless this is rectified very quickly, I will expect a
full refund of all monies paid and removal of all of my private files from your
backup servers.

Their answer to this was of the cut-and-paste variety, and almost passive-aggressive in its tone. And what angered me further was that they seemed to be completely ignoring my point – that they can’t just make it up as they go along.

Hi Alan,

I am sorry to hear you wish to cancel.

The last thing we don't want to frustrate our customers, we had to put these
additional charges in place to keep running our subscriptions at such a low price.

As a valued customer we would be happy to offer you the Video Backup ***and/or*** Files
over 1GB add-on for free.

I just want to clarify that it is still possible to Drag & Drop or right click on
a file that is anywhere of any type and back it up without these additional services.

Please confirm how you want to proceed.
--
--
XXXXXX XXXXXXXX
User Experience Team
www.JustCloud.com

But to tell me that they “…had to put these additional charges in place to keep running our subscriptions at such a low price” – a startling tacit admission that they were, in fact, making it up as they went along. There’s the court case winner right there, in a single sentence.

My next email was this:

The one thing you are doing, at least in this case, is frustrating a
customer. It's fairly outrageous that you can decide to move the goalposts
and tacitly admit to breaking your contract. Clearly, I am not a valued
customer as you have just asked me to fork out an additional EUR 240 per
year for the service you have already agreed to provide to me. It's not my
fault your company has not properly costed its offering.

Also, do you see the ridiculous irony in charging a *lot* more in order to
"keep running our subscriptions at such a low price"? This is management
speak at its worst and I'm not falling for it.

Please cancel and refund my subscription payment, in full, as soon as
possible. And please remove my backed up files from your servers. I will
report this to Visa if my refund is not complete, to the penny. And I will
get it too. I paid for two years up front. You really have quite a cheek
forcing me to pay more, at this point, to get the same service you
contracted with me to provide.

I will now have to look again for an alternative replacement service, and
for a service that is somewhat more trustworthy. I expect this behaviour
will damage your business, and I don't care if it does. I will
also take steps to warn those friends of mine I had already recommended your service
to of this experience. And I will make a larger audience aware of it too.
This sort of nefarious practice will simply not stand.

Sincerely
Alan Shanahan

After a couple of days I checked my credit card statement and saw that they had refunded me all of my payment, less approx. EUR 13 which I can only presume they kept to pay for using their time in responding to my emails. Call me a coward, but I couldn’t be bother going through the admin headache of chasing it.

By chance, I came across this Facebook page: Avoid JustCloud

I was not alone. It’s a fair assumption that you will only ever hear of a small percentage of unhappy customers, because many people will not take it upon themselves to chase these things up, complain openly or to join such unhappy public forums.

It’s outrageous that a subscription business thinks this type of nefarious practice will stand: simply because they cannot accurately build a cost model into their business. Getting a small minority of (potentially) loyal customers to pay for their business risks is no way to guarantee business survival; if anything, it’s only going to help guarantee failure. Do we really have to return to Business 101 by stating that the most important asset of a business is NOT its people, it is the CUSTOMERS? For the record, I actually annoyed myself typing that.

There are some damning reviews at this link: C|Net user reviews of JustCloud

I could continue to bore you with the subsequent relentless emails I got from them – almost as if none of this had happened – but I won’t. An automated marketing engine totally lacking in intelligence or any form of personal touch, all of which was glaringly obvious.

I wonder how much of my recurring business they lost. And how many lost referrals, on my part. And who will read this and decide not to use them? That’s one hell of a business strategy.

My message to the owners of JustCloud: Unless your business is comedy, don’t let comedians run your business.


4 Comments

Force.com: Visualforce programming, position cursor at first input field

When building a custom Visualforce page with input fields, one common requirement is to place the cursor at the first input field on the page. You would think this would be a simple matter and Salesforce itself manages the task quite well. But when the platform’s default behaviour kicks in and overrides your page’s behaviour, it doesn’t always work smoothly. Or if you want to position on an input field that is not a text entry field it doesn’t always slide into place. Or perhaps you wish to show a dialog box where you wish to conditionally position the cursor to a Confirm or Cancel button depending on prior processing.

In this piece, I’m offering a foolproof way to enable your page to behave exactly as you want it to, in an easy, maintainable way. Here is the step by step way to do this.

First, download a copy of the JQuery library from jquery.com. The minimised (compressed) version is just fine.

Now, upload it to your Salesforce org as a Static Resource.

In your Visualforce page, add this line somewhere after the apex:page tag:

<apex:includeScript value="{!$Resource.JQueryJS}" />

…making sure to replace the JQueryJS text with the name you specified during the Static Resource upload step.

The code below assumes that the page is aware of a “mode” or action passed to it, perhaps as a querystring parameter and parsed separately into a variable called wrkAction.


...

	<script language="JavaScript">

	//----------------------------
	// JQuery initialisation
	//----------------------------
	j$=jQuery.noConflict();
	j$(document).ready(function() {
		initialisePage();
	});

	//-------------------------
	function initialisePage() {
	//-------------------------
		positionCursorToFirstField();
	}
	//-------------------------------------
	function positionCursorToFirstField() {
	//-------------------------------------
		if ('new' == '{!wrkAction}' || 'edit' == '{!wrkAction}' || 'copy' == '{!wrkAction}') {
			j$("[id*=':btnConfirm']").focus();
		}
		if ('del' == '{!wrkAction}') {
			j$("[id*=':btnCancel']").focus();
		}
	}
	</script>

The page buttons might be defined later in your page code, as follows:

	<apex:pageBlockButtons id="pbButtons" location="bottom">
		<apex:commandButton id="btnCancel"  value="Cancel"  immediate="true" onclick="return checkCancel();"  />
		<apex:commandButton id="btnConfirm" value="Confirm" immediate="true" onclick="return checkConfirm();" />
	</apex:pageBlockButtons>

Given that any page element will probably exist in the hierarchy of page elements, the Visualforce page is rendered with the implicit force.com naming applied i.e. the full “pathname” to the element is implied in the name, with colons separating each branch in the tree. For example, an HTML id such as j_id0:j_id1:j_id192:j_id193:j_id196:j_id230:j_id231:j_id232:4:j_id236 would not be unusual.

The above code brings a “best practice” tip to mind – always use page-unique ID values for input fields, buttons and all other page components. Specifying the ID tag also ensures that the force.com implicit naming conventions are not applied.

The JQuery code in the positionCursorToFirstField javaScript method above provides a major advantage: you are now effectively freed from having to worry about the naming hierarchy. The JQuery selector finds the field ending with a colon character followed by the specified unique fieldname. This also means you can move it around on the page and within the page element hierarchy (DOM) and not have to worry about this code failing or needing to be modified.

There’s just one more piece of code needed to ensure the force.com standard processing doesn’t happen i.e. that the platform itself doesn’t try to be too clever and preempt what you’re trying to do. This code masks the effect of the standard “first input field positioning” processing:

	<script language="JavaScript">

	//--------------------------------------------------------------------------------------------------------------
	// This empty function overrides the SFDC standard function, and enables us to control initial field positioning
	//--------------------------------------------------------------------------------------------------------------
	function setFocusOnLoad() {
	}

	</script>