Category Archives: Pontificating

My Disordered Rebuttal to “AngularJs Performance in Large Applications”

After reading Abraham Polishchuk’s article AngularJS Performance in Large Applications, I wanted to dig a bit deeper on his suggestions before I took any of them on board. My basic concern was many of his suggestions seemed focused around technology-specific performance micro-optimisations. In today’s browser world, optimising around specific technologies (i.e. browsers and browser versions) is an expensive task with a limited life and usefulness: both improvements in the Javascript engines and differences in browser implementations mean that these fine-grained optimisations should really be limited to very specific performance critical situations.

Conversely, I don’t think we can expect Angular’s performance to improve in the same way as browser engines have. While Angular has undergone significant iterative performance improvements in the 1.x series, it is clear from the massive redesign of version 2.0 that most future application performance gains will only be won by rewriting significant chunks of your own code. Be aware!

Understanding computational complexity is crucial for web developers, even though with Angular it is all Javascript and browser and cloud and magic. You still need that software engineering education.

Onto the article.

1-2 Introduction, Tools of the Trade

No arguments here. Helpful.

3 Software Performance

Ok.

4.1 Loops

This advice, to move function calls out of loops, really depends on what the function you are calling is. Now, clearly, it’s sensible to move calls out of a loop if you can – that’s a normal O(n) to O(1) optimisation. And Objects.keys, as shown in the original article, is very heavy function, so that’d be a good one to avoid.

But don’t take this advice too far. The actual cost of the function call itself is minimal (http://jsperf.com/for-loop-perf-demo-basic/2). In general, inlining code to avoid a function call is not advisable: it results in less maintainable code for a minimal performance gain.

4.2 DOM access

While modifications to the DOM should be approached carefully, the reality is a web application is all about modifying the DOM, whether directly, or indirectly. It cannot be avoided! Applying inline styles (as opposed to using CSS selectors predefined in stylesheets?) vary significantly depending on both the styles being set and the browser. It’s certainly not a hard-and-fast rule, and not really a useful one. In the example, I compare background color (which should not force a reflow), and font-size (which would): (http://jsperf.com/inline-style-vs-class). The results vary dramatically across browsers.

4.3 Variable Scope and Garbage Collection

No arguments here. In fact I would go further and say that this is the single biggest performance concern, both in terms of CPU and resource usage, in Angular. In my limited experience, anyway. It’s very easy to leak closures without realising.

4.4 Arrays and Objects

Yes. Well, somewhat. As Gregory Jacobs commented, there is no significant difference between single-type and multi-type arrays. The differences come in what you are doing with the members of that array, and again browsers vary. http://jsperf.com/object-tostring-vs-number-tostring

I would again urge you to avoid implementation-specific optimisations. Designing an application to minimize the number of properties in an object just because today’s implementation of V8 has a special internal representation of small objects is not good advice. Design your objects according to your application’s requirements! This is a good example of a premature optimization antipattern.

Finally, as Wills Bithrey commented, Array.delete isn’t really slow.

5.1 Scopes and the Digest Cycle

This is a clear description of Angular scopes and the digest cycle. Good stuff. Abraham does a good job of unpacking the ‘magic’ of Angular.

6.1. Large Objects and Server Calls

Ok, so in my app I return full rows of data, and there are a few columns I don’t *currently* use in that data. I measured the performance impact on my application, and the cost of keeping those columns was insignificant: I was actually unable measure any difference. Again, this is a premature optimization antipattern. Your wins here will ultimately not be from excluding columns from your data but from making sure your data is normalized appropriately. This is about good design, rather than performance-constrained design.

Of course, there are plenty of other reasons to minimize your data across the wire. But remember that a custom serializer for each database object is another function to test, and another failure point. Measure the cost and the benefit.

6.2 Watching Functions

Yes. Never is a little too strong for me, but yeah, in general, avoid binding to functions.

6.3 Watching Objects

Yes, in general, deep watching of objects does introduce performance concerns. But I do not agree that this is a terrible idea. The alternative he gives (“relying on services and object references to propagate object changes between scopes”) gets pretty complicated and introduces maintenance and reliability concerns. I would approach this point as potential low hanging fruit for optimisation.

7.1 Long Lists

Yes.

7.2 Filters

As DJ commented, filters don’t work by hiding elements by CSS. Filters, as used in ng-repeat, return a transform of the array, which may be what Abraham meant?

7.3 Updating an ng-repeat

Pretty much. I would add that for custom syncing to work, you still need a unique key, just as you do for track by. If you are using Angular 1.3, there’s no benefit to the custom sync approach. Abraham has detailed the maintenance cost of custom syncing.

8. Rendering Problems

ng-if and ng-show are both useful tools. Choose your weapons wisely.

9.1 Bindings

Yes.

9.2 $digest() and $apply()

Yes, if you must. This is a great way to introduce inconsistencies in your application which can be very hard to debug!

9.3 $watch()

I really disagree with this advice. scope.$watch is a very practical way of separating concerns. I don’t think it’s indicative of bad architecture, quite the opposite in fact! While trying to find the discussions that Abraham refers to (but sadly doesn’t link to), it seemed that most of the alternatives given were in fact in themselves bad architecture. For example, Ben Lesh suggested (although he has since relaxed his opinion) using an ng-change on an input field instead of a watcher on the target variable. Why is that bad? From an architectural point of view, that means each place in your code that you change that variable, you have to remember to make that function call there as well. This is antithetical to the MVC pattern and seriously WET.

9.4 $on, $broadcast, and $emit

Apart from the advice to unbind $on(‘$destroy’) which I don’t think is correct, yes, being aware of the performance impact of events is important in an event-driven system. But that doesn’t mean don’t use them: events are a weapon to use wisely. Seeing a pattern here?

9.5 $destroy

Yes. Apart from the advice to “explicitly call your $on(‘$destroy’)” — I’m not sure what this means.

10.1 Isolate Scope and Transclusion

Only one quibble here: isolate scopes or transclusions can be faster than occupying the parent scope, because a tidy directive can use $apply to just update its own isolated scope, and avoid the digest of the entire scope tree. Choose your tools wisely.

10.2 The compile cycle

Basically, yes.

11 DOM Event Problems

Yes, addEventListener is more efficient, but so is not using Angular in the first place! This results in a significant code increase and again you the benefit of Angular in doing so. Going back to raw DOM is always a trade-off. In the majority of cases, the raw DOM event model is a whole lot of additional work for little gain.

12 Summary

In summary, I really think this post is about micro-optimisations that in many cases will not bring you the performance benefits you are looking for. Abraham’s summary suggests avoiding many of the most useful tools in Angular. If you have to roll your own framework code to avoid ng-repeat, or ng-click, you have already lost.

Have I got the wrong end of the stick?

How many TLDs is too many?

So I got my usual daily email from $registrar today, telling me that my world is going to change and I just have to, have to, buy a new domain name from them for the today’s brave new TLD. Today’s must-have TLD is .website, and yesterday’s was probably .ninja. I’m offended on behalf of Samurai, because I wasn’t offered a .samurai domain.

Today’s must-have TLD is .website.

I enclose below a snippet from the email. I think it speaks for itself:

generic

A morbid fascination caused me to click the link provided. I was given a list of 236 different TLDs, ranging in price from $8.98 for .uk (which, by the way, I can’t actually buy), all the way through to a princely $3059.99 for .healthcare.  I was surprised that .dental was so affordable, at a mere $59.99.

Here’s the list I was offered (click for the gory detail):

keyman-domains

I have a few keyman.* domains already, purchased over the years before we managed to acquire our blue label keyman.com.  It’d be nice to fill out the collection. So how much for the full set? Well, the full set of “New Domains” offered by one particular registrar, anyway. Today only, the full set will cost just $26,761.45. That’s doesn’t include most of those two letter country domains, .la and .io and .tv.

Today only, the full set will cost just $26,761.45.

My view is that every TLD issued now increases the value of keyman.com.  I can’t see any way that the average small company is going to be blowing $25K a year on maintaining a set of worthless domains, just to prevent squatters or even to maintain a registered trademark. Some very large companies might find it worthwhile to register, e.g. microsoft.tax. But me? Nup. I’m not renewing some of my unused lower value domains, and you’re welcome to them.

The gold rush is over people.

Cursor Keys Have Not Improved

I’m a keyboard guy. And I think keyboards suck. In fact, I wrote about this before

I found two new ugly specimens for today’s little rant, and your perusal. Both these keyboards have a reasonably traditional layout, but both fail, for different reasons. These two keyboards were in our conference room.

Microsoft Wireless 800

What’s wrong with this?

  1. It has no gaps between the different parts of the keyboard. Muscle memory fail.
  2. It has a bizarre scooped out shape, not really visible in the photo, which seems to encourage pressing the wrong row of keys.
  3. It has no gaps. This is so bad that it bears repeating. Without gaps, you have to look for the key because you can’t feel for it. Every time.

I thought I was the only one who really hated this keyboard with a passion, but enough other people complained about it that we replaced it with a Dell keyboard. I don’t know what has happened to the Microsoft keyboard. It’s entirely possible someone burned it.

Dell Latest

So this one, at first glance, improves on the Microsoft keyboard by reintroducing that classic design feature: white space, or black space. Just space. Y’know, gaps between different parts of the keyboard. Space is not entirely at a premium on our conference room table. But:

  1. The keys are modern funky flat keys with an unsatisfying deadness to them.
  2. The wrong size! Little tiny navigation keys for big fingers.
  3. And the media keys are encroaching on the navigation key space.
  4. What is the Clear key for? And what have you done with Num Lock? And Scroll Lock? And Pause/Break?
  5. I have nothing against the moon, but why do we need a moon key on our keyboard?

These things cost us time and productivity. It may seem minor, but moving between keyboards has become a constant frustration. I wish we as an industry could do better.

Everything you (thought you) knew about Internet password security is wrong

Time and time again, we see calls from security experts for complex passwords.   Make sure your password includes lower case letters, upper case letters (how xenoglossophobic!), numerals, punctuation, star signs, and emoji.  It must be no less than 23 characters long and not use the same character twice.  Change your password every 60 days, every 30 days, every half hour.  Don’t use the same password again this year, or next year, or for the next 6 galactic years.  Never write your password down.  Especially not on a post-it on your monitor.  Or under your keyboard.
d00fus

The Golden Password Rules

And it’s all wrong.  There are just two rules you need to remember, as an Internet password user:

  1. Never use the same password in two places.  Like, if you have a Yahoo account and a Google account, don’t let them share the same password.  They’d be offended if they knew you did anyway.
  2. Make sure your password isn’t “guessable”, like your pet’s name, or your middle name.  Or anyone’s middle name.  Or “password”.  Or anything like that.  But “correct horse battery staple” is probably ok, or it was until xkcd published that cartoon.

It’s all wrong because all that complexity jazz is just part of an arms race in the brute force or dictionary attack password cracking game.

Say what? So a brute force attack is, in its simplest form, a computer — or hundreds of computers — trying everything single password combination they can think of, against your puny little password. And trust me when I say a computer can think of more passwords than you can. Have you ever played Scrabble against a computer?

Brute force attacks on Internet passwords are only effective on well designed sites when that site has already been compromised.  At which point who cares if they know your password to that site (because rule 1, remember): they also know everything else that site has recorded about you.  And anyway you can just change that password.  No problem (for you; the site owners have a big problem).

Now, if you are unlucky enough to be targeted, then complex passwords are not going to save you, because the attackers will find another way to get your data without needing to brute force your Google Apps password.  We’ve seen this demonstrated time and time again.  And if you are not being targeted, then you can only be a victim of random, drive-by style password attacks.  And if you followed rule 2, then random, drive-by style password attacks still won’t get you, because the site owner has followed basic security principles to prevent this.  And if the site owner has not followed basic security principles, then you are stuffed anyway, and password complexity still doesn’t matter.

In fact, complex passwords and cycling regimes actually hurt password security.  The first thing that happens is that users, forced to change passwords regularly, can no longer remember any passwords.  So they start to use easier to guess passwords.  And eventually, their passwords all end up being some variation of “password123!”.

The Bearers of Responsibility

The people who really have to do the hard yards are the security experts, software developers, and the site owners.  They are the keepers of the password databases and bear a heavy burden for the rest of us.  Some suggestions, by no means comprehensive, for this to-be-pitied crew:

  1. Thwart dictionary attacks on Internet-facing password entry.  That is, throttle connection attempts, delay for 15 seconds after 10 attempts, require 2nd level authentication after failed attempts, that kind of thing.  These solutions are well documented.
  2. Control access to your password database (duh).  Remember, in the good ol’ days of Unix, password were stored in /etc/passwd, which was world readable and so the enterprising young hacker could just copy the file and try and crack it in their own good time elsewhere.  So keep other people’s dirty paws off your (hashed) password database.
  3. Don’t ever display passwords in plain text.  No “here is your password” emails.  Not even for registration.  That has to be a one time token.  Your password database is hashed, right?  Not ROT13?
  4. Notify a user if someone tries to access their account multiple times.  Give them the power to fret and stress.
  5. If your site gets hacked, tell your users as soon as you possibly can, and reset your password database.  Mind you, they’ll just have to change their password for your site because they’ve been following rule 1 above, right?  Oh, and don’t be too ashamed to tell anyone.  It happens to all the best site owners and there’s nothing worse than covering it up.

The Flaw in My Rant

Still, my rant has a problem.  It’s to do with Rule 1:  A separate password for every site.  But just how many sites do I have accounts for?  Right now?  402 sites.

Yikes.

How do I manage that?  How can I remember passwords for 402 sites?  I can’t!  So I put them into a database, of course.  Managed by a password app such as KeePass or 1Password or Password Safe. Ironically, as soon as I use a password manager, I no longer have to make up passwords, and they actually end up being random strings of letters, numbers and symbols. Which keeps those old-fashioned password nazis happy too.

Personally, I keep a few high-value passwords out of the password database (think Internet Banking) and memorise them instead.

Of course, my password safe itself has just a single password to be cracked.  And because I (the naive end user) store this database on my computer, it’s probably easy enough to steal once I click on that dodgy link on that site…  At which point, our black hat password cracker can roll out their full armada of brute force password cracking flying robots to get into my password database.  So perhaps you still need that complex password to secure your password database?

What do you think?

Note: Roger Grimes stole my thunder.

Rant: Why can’t Microsoft provide actually useful titles on their updates?

Windows Updates have improved dramatically over the last few years.  With Windows 7, the integrated updates install smoothly and without much fuss (apart from the occasional EULA or Internet Explorer Upgrade to throw a spanner in the works).

There’s just one thing.  In general, the update titles are useless.  Completely useless. “Security Update for Windows 7”? Why else would I be running Windows Update?

update-2

Furthermore, the detailed description is also useless — it doesn’t actually provide any details!  It’s even more ambiguous than the title! “A security issue has been identified in a Microsoft software product that could affect your system.”

update-1

Let’s look at what’s wrong with “Update for Windows 7 for x64-based Systems (KB2830477)”:

  • It doesn’t tell us what the update actually provides
  • We already know it’s for Windows 7 — that’s in the group title.
  • We don’t need to know it’s for x64-based Systems — Windows Update won’t serve us updates for the wrong system type

We couldn’t we see “Update for RemoteApp and Desktop Connections features is available for Windows (KB2830477)”, instead? So which sleeve did I pull that descriptive and useful title from?

Well, the thing is, Microsoft already do know exactly what the update is providing.  They have even taken the time to write a succinct title for the update: it’s the title of the Knowledge Base article associated with the update, and it’s even linked to from the update. For example, instead of “Update for Windows 7 (KB2852386)”, we could have “Update: Disk Cleanup Wizard addon lets users delete outdated Windows updates on Windows 7 SP1 (KB2852386)”

Now it’s even worse when using WSUS — you now have to trawl through hundreds of nearly identically titled updates, with only a KB article number to differentiate.  So easy to accidentally approve the wrong update.  Why, Microsoft, why?  Is it so you don’t scare consumers who don’t understand what the update provides?  They just press the big “Automatic Updates” button anyway!

update-4

Admittedly, Microsoft have taken a big step in the right direction with Visual Studio updates: the description for Visual Studio updates generally gives you some information about what is being updated:

update-3

But even that could be improved. We’ve got a lot of repeated information: “Visual Studio 2010” is referenced 4 times: in the group title, in the update title, in the update title in the preview pane, and in the description of the update, again in the preview pane! Surely we don’t need to know that 4 times! And why don’t we go with a title of “Update fixes coded UI test issues for Visual Studio 2010 SP1 in IE9 or IE10 when KB 2870699 is installed (KB2890573)”. Sure it’s a little bit long, but it’s better than “Update for Microsoft Visual Studio 2010 Service Pack 1 (KB2890573)”.

So in conclusion, may I ask you, Microsoft, please, fix these update titles? Just start giving us titles that mean something? And if you are feeling particularly generous, you could even update the description of the update to add more meaning, not less!

The farce of security challenge questions (yes, ANZ, I’m talking about you!)

My bank has decided that I have to have some security challenge questions, and gave me a fixed set of questions to add answers to.

They had some simple instructions: “Keep them secret and don’t disclose them to anyone.  Don’t write down or record them anywhere.”  And added a little threat as icing on the cake: “If you don’t follow these instructions, you may be liable for any loss arising from an unauthorised transaction.”

Security Questions 1 Security Questions 2 Security Questions 3If I actually attempt to give honest answers to the questions, any determined and reasonably intelligent hacker could find the answers to all the questions that I actually know the answer to, within a minute or two, online, tops.

So what if I opt to use 1-Password or another password management tool to generate secure and random “password” style answers to these questions?  These would not be readily memorisable and so I’d have to save them in the tool.  But according to their little threat, I can’t do that!  That’s called recording the answers to the questions and I could be liable if an unauthorised transfer occurs.

The real problem with questions like this is that too much of this information is recorded online, already.  It adds a layer of complexity to the security model, without actually improving security much, if at all.

Then another question arises.  If an acquaintance does happen to ask me where I got married, am I now liable to ANZ if I tell them?  It sounds ridiculous but lawyers be lawyers.  Mind you, given that I have no way of not agreeing to the terms, perhaps it’s unenforceable.  The whole thing is really badly thought out.

Update 9:46am: Blizzard and insecurity questions: My father’s middle name is vR2Ut1VNj is a really good read for more detail!

Our collective wrongs

It has been said that every generation and every culture harbour a collective wrong. When we read through history, it is easy to find cultural attitudes and actions which violate the rights of a group of people. These attitudes are often couched in pseudo-scientific terms, and dehumanising phrases are commonly used by the proponents of these attitudes. Societies’ leaders would use moral imperatives in support of their arguments. In some cases, these wrongs were even perpetuated by well-meaning people with a sadly misguided world view.

Those who spoke out against what they saw as grievous wrongs were marginalised, or even hunted down.

First they came for the communists,
and I didn’t speak out because I wasn’t a communist.

Then they came for the socialists,
and I didn’t speak out because I wasn’t a socialist.

Then they came for the trade unionists,
and I didn’t speak out because I wasn’t a trade unionist.

Then they came for me,
and there was no one left to speak for me.

– Martin Niemöller

These injustices have ranged from the tragic (stolen children) through to the terrible (slavery), right through to the monstrous (Nazi genocides).

It is easy to look back at our ancestors and condemn their actions. But are we as a society, today, ready to examine our own motives, understandings, and prejudices?

What are our collective wrongs? What injustices do we not see, or see, and not speak out against?

Rant of the day: The Big Green Download Button

What is it with software download sites and their download links?  Typically if you visit a website to download software, especially free or open source software, you’ll be presented with a page with several big green download buttons.  Often the actual download will be a link buried to one side or somewhere halfway down the page.  Nearly every site offering free software does this.  And it sucks.

You may argue that it is the ad network providing these ads, but the developer of the site has chosen to put ads on their page.  They know that the ads are misleading.  And yet they persist.

Do you want to see some examples?

The actual download link is below the fold for most users.  A subtle ‘Advertisement’ box which most users will simply miss.

 

Paint.net does it twice: on their download page, and then on the download host page.

 

Spot the real download link: it isn’t a big friendly green button, is it?

 

“Reputable” sites such as Sourceforge also do it.  A little link for the real download.  And big green Download buttons for the fake ones.

 

Four fake downloads at FileHippo.  Can you see them all?

 

CNet manage to have two fake downlaods.  Amazingly, slightly less offensive than most of the others, apart from the irritating animated ad.

 

Brothersoft is particularly bad.  The actual download link is further down the page.  I count ten download links above the fold.

Developers, leaving ads like this on your software download pages hurts your users.  Using file distribution sites such as the ones illustrated above, that bury your software download link among all their ads, hurts your users.

Inexperienced users will download the wrong program and end up frustrated and angry that you tricked them into installing rubbish they didn’t want.

More experienced users will usually see past the ads but it will still be a frustrating experience for them, and gosh does it look like seedy hour.  It feels like visiting a warez site.  Your reputation is tarnished.  It’s nearly as bad as bundling toolbars (and we all know how that makes you look!)  You look cheap.  And nasty.

Gurus use Adblock.  They won’t see your ads.  You won’t get revenue from them.  And over time, they are teaching the inexperienced users to install Adblock so that the less experienced users get the software they want, as well.

Note how Adblock do not have any other green download buttons but their own.  Yeah, the page is ugly, but at least they got their download button right!

Get rid of those low-life ads!  Build a reputation of delivering your software yourself, from your site, without misleading advertisements.  That’s my rant done.

Corrie: why is she a hero?

“Father sat down on the edge of the narrow bed. “Corrie,” he began gently, “when you and I go to Amsterdam-when do I give you your ticket?”
I sniffed a few times, considering this.
“Why, just before we get on the train.”
“Exactly. And our wise Father in heaven knows when we’re going to need things, too. Don’t run out ahead of Him, Corrie. When the time comes that some of us will have to die, you will look into your heart and find the strength you need-just in time.”
― Corrie Ten Boom, The Hiding Place

Corrie Ten Boom suffered more than most of us ever will. And yet she was full of love. She had learned to live in the grace of God. Through the most devestating of circumstances, she depended on Him and His grace was sufficient for her needs.
If that bleak, black time comes for us, I guess all we have to do is ask our Lord for that grace. But perhaps the hardest thing of all is to do just that: it means giving up the hate and giving the hurt to Him, just to make that simplest of requests. No revenge, just forgiveness is all that can remain. He will help us, if we just once ask Him.
Corrie Ten Boom is one of my heroes, for she did not survive the most awful of times on her own willpower, or through determination, or even by being a super holy person. She is my hero because she was able to ask God for that grace.
I pray that I may be spared such sufferings. And yet, that if such sufferings come my way that He will protect my soul and not allow it to become hardened with resentment or hate. And that I can continually ask Him for that grace freely provided by the sacrifice He already made through His son, which purges our sins, and by so doing allows us to love those who have hurt us.

What value my life?

I sometimes ponder on what I value in my life. Or to put it another way, what it would mean to lose certain things. I go through the things, the activities, the people in my life and imagine what it would be to no longer have them there. My house? It’s a lovely house… We put a lot of effort into building it and I enjoy living in it. All the same, I can imagine not having it, and it doesn’t hurt that much. It’s a place to live and I thank God for His provision and yet I don’t feel bound to it. My car? Pfft. It gets us from A to B and the thing I value most about it is that it rarely goes wrong.

So how about my bike? I certainly enjoy riding it. But it just costs money to replace, and God has blessed us with enough money to buy a bike. I don’t feel so attached to the bike itself. Ok then, how about cycling itself?

I do love riding my bike. The challenges, racing and riding with mates, pushing myself physically, the exercise and the well-being it brings. And yet… I could let it all go, and my only real regrets would be losing touch with riding buddies, and the loss of fitness. I’d miss riding, but it wouldn’t destroy me.

My job, my career? The code I create — Keyman; the business I’ve poured myself into — Tavultesoft; and the relationships built, respect earned? I derive a lot of satisfaction from creating computer software: turning a concept into a tool that can really help people. So what if that all disappeared? My position, my abilities, my reputation, my creations? Would that devastate?

It would hurt. I’m sure it would hurt more than I can really imagine. And yet, I can imagine a world without this job. I can’t imagine what I would do, but I can imagine it.

And so as we cut closer to the quick, I start to draw back. All these various blessings of God — those that I take for granted through to those that I spend much of my waking life focused on — stripped away. Like Job. What if it happened to me? Can I really comprehend the pain of the loss of all that?

That pain. It would be as nothing to the loss of my family. That’s the one place I cannot imagine arriving at. The loneliness, my tether to reality severed, my life, my soul, spinning through the void. My wife and daughters: those who are so close and can infuriate, hurt, and exasperate. Those three people who bring such joy to me, a joy that others can only glimpse a pale reflection of when I post a comment on Facebook, or drop an email to them. Even to contemplate losing them stops my heart and starts a cold, cold hurt deep within.

I can’t imagine it. I shy away from the very idea. Job lost his whole family, everything, and yet he would not curse God, nor turn from Him. Do I have such a love for Him that I could continue to worship Him in the face of such devastation? To look for comfort, probably. To be angry with Him, almost certainly! But to worship Him? I don’t know, and my prayer is that He would not allow me to suffer to such a degree that I could come to doubt His love for me.

It is a selfish prayer. So many people in this world suffer such loss that I couldn’t bear. I sit here safe and contemplate this from the safety of my warm home, with my family around me, in a safe and comfortable country. Lord God, shatter me, make me dependent on You and You alone. I am too scared to ask this of You. But this is my tiny step of faith. I am like the father who asked Jesus “help me believe!”