Showing posts with label nodejs. Show all posts
Showing posts with label nodejs. Show all posts

Monday, October 3, 2016

Beyond the UI: Pitfalls and Best Practices in JavaScript

When I was asked to present at DevCon about JavaScript, there were a lot of things that came to mind - new things I was exploring that I found exciting and long-held beliefs I am generally eager to act as evangelist for - many of those were dismissed as I talked to the conference organizers and they asked that I "go back to basics" but somehow cover both user-agent JavaScript and JavaScript in Node. With that suggestion in mind, I came to this - the pitfalls and best practices in JavaScript.

A little research has revealed that 0.2 percent of web traffic is from user agents that either do not have JavaScript available as a feature or have JavaScript disabled. That means a whopping 99.8 percent of user agent traffic has JavaScript in the front-end. If we add back-end and middle layers that use JavaScript through things like node.js, it's pretty easy to see that JavaScript is everywhere.

While 99.8 percent of front-end traffic is from user agents with JavaScript enabled, it is still very easy to functionally disable JavaScript, and when that happens, everything from simple interactions to complex Single Page Applications fail, and can leave your users - your customers - staring at a blank page. That's not acceptable. That means we must write good code. How do we do that?

Writing code is a skill - which means it can be taught and practiced - and practice is really the only way we get better at any skill, but that's where we often go wrong.

My daughter studies Irish dance, and I asked her one day how she could get better so she could advance to the next grade, and she responded that her teacher told her "practice makes perfect". Seeing what we parents like to call a "teachable moment", I asked her what would happen if she practiced her dances, but practiced the wrong steps - what if she put the steps of her reel in the place of her light jig, for instance? Our discussion of the possible outcomes ranged from disqualification - or as she likes to call it, "getting a big fat zero" - to possibly winning a medal if the judge(s) didn't notice the difference.

That's when I told her that it's not the practice, that makes perfect - it takes more. It's perfect practice that makes perfect. It's not enough that she just practice - she has to practice the right steps, and that's how it is with writing good code. It's not a matter of how practiced we are, it's a matter of how much we've practiced the right things.

So, what are the right things when it comes to good code? Ultimately, good code is good writing. Yes, we're solving a problem, but if we look at it another way, we are telling a story about how to solve the problem. What are the elements of good code - the same elements as good writing.

Good writing has clarity and focus. As engineers who have built object-oriented code for two decades, we pretty much have the 'focus' element down - we just call it 'encapsulation'. Clarity, on the other hand, could use some work.

Good writing is organized. Back in day, we struggled against spaghetti code. We've gotten beyond that now, especially with event-oriented programming, where we have the very real threat of callback hell.

Good writing uses precise language. It says exactly what it means. Here, we can think about data types and how we speak or write outside of code. If you use the word biker in one community it may mean something entirely different in another, and likely does. That word, in a sense, refers to two different data types and is, unfortunately, not very precise.

Good writing uses correct grammar and style. Again, one of these - the grammar portion of the rule - we have down. The syntax is the syntax, and there isn't really a way around it. The style portion of the rule doesn't refer to your "personal style", rather it refers to the stylistic elements like how indentation and braces are used. Using incorrect style is something like dropping a comma from a sentence. We, of course, realize there is a big difference between "it's time to eat, grandma" and "it's time to eat grandma".

Good writing expresses the author's voice. This is your personal style - what makes your code different than code written by someone else. This encompasses things like which substring function you use or how you build a string - whether you use an array and join or the plus operator. These are the things we sometimes don't even notice unless they're vastly different than our own way of doing things.

Ultimately, it all comes down to one thing - we can describe good code in terms of how understandable the story is to other people, because "any fool can write code that a computer can understand; good programmers write code that humans understand".

Now, let's put these elements in terms of best practices that help us understand how we can achieve clarity and focus, how we might approach organization, what it means to use precise language, and what correct style is.

In the language of those who evaluate and manage risk, we hear about "known knowns", "known unknowns", and "unknown unknowns". After nearly two decades of experience with a language and millions of developers all over the world writing in it, we've pretty much identified all the gaps in the language. We often still struggle with where the gaps are in our applications. In a sense, we know that we're missing a piece of the map, but we don't really know what that piece of the map represents.

Is Sky Broadband familiar to anyone? Sky Broadband is a large Internet Service Provider in the UK, and in the early days of 2014, Sky Broadband mistakenly marked the subdomain code.jquery.com as malware - the entire CDN repository. Suddenly pages all over the UK stopped working - the user experience for literally millions of users was ruined, regardless of whether it was a simple interaction or a more complex application.

Of course this not only happens in front-end code, it happens elsewhere as well. It can even happen in Nodejs applications - anywhere JavaScript is used.

Earlier this year, NPM involved themselves in a brand infringment disagreement that was originally between a developer who had several published modules and an organization who wanted to use the name one of his modules used. After NPM acted, the developer pulled all his published modules from NPM, including the eleven lines of code published as 'left-pad'. When that module was pulled, thousands of projects broke before NPM restored the module.

We can debate the ethics around this second example, but in this case it's worth noting that it was eleven lines of code that padding a string on the left side. It wasn't a complex, multifunction library - its removal should not have broken thousands of projects.

You must always know not only what your dependencies are and where they are, but what they do. Put them squarely in the known unknowns column so you can guard yourself against the time when they disappear, or are blocked by an ISP, or are broken in the new release, or any one of the many things that can happen. Not fully identifying dependencies can result in a poor debugging and support experience as well as a poor - or worse, non-existent - user experience while you resolve dependency issues that arise, so the first item on the list of what will be ten principles is to identify dependencies.

We come to it at last. The great battle of our time. And it's the kind of battle few but engineers can have - a battle about design patterns. Make no mistake, nearly everyone takes a side in this battle, but it's no battle between the five armies and the forces of Sauron - there is no good side or evil side - just two competing ideas, each with advantages and disadvantages.
The debate between proponents of the Module Pattern and the Prototype Pattern can be severe; however, if you keep an open mind you will see that these patterns are not terribly dissimilar. The Module Pattern offers advantages in clarity that the Prototype Pattern does not - an advantage more pronounced in teams with greater history in Java development. The Prototype Pattern offers advantages in memory management and performance that the Module Pattern does not - although that advantage can be lessened by applying strict structures and development practices.

By keeping an open mind with an eye focused toward design concerns, you can more easily determine which pattern is appropriate for your needs. It may also be the case that one design pattern is used in a specific context and the other used in a different context; however, I would generally advise against such an arrangement due to the loss of clarity with the reduced consistency. Most importantly, however, the second item on our list of principles is to identify design concerns.

The next contentious debate - albeit one that has died down in recent years - is about indentation style. Years ago, when I was first writing code - about the same time the movie Highlander was released - the hot programming language was C and the indentation and brace style was called K & R - for Kernhigan and Ritchie and The C Programming Language. JavaScript, unlike other languages, has some quirks - different ways of handling control statements and white space and an implied semicolon, or automatic semicolon insertion, for instance. Unfortunately, this sort of behavior could lead you to lose your head if you're not careful, which is why every engineer with more than a modicum of experience with JavaScript will tell you to use the One True Brace Style, or OTBS - because there can be only one.

Here we'll take a look at some statements that use different brace and indentation styles. On the left you'll notice the if statement has no brace but the return statement is indented. In a language such as Python, this would indicate that the return should occur only when the conditional is true; however, in JavaScript the if statement without a brace will only consider the next newline part of the conditional, meaning the return statement will happen every time, not just when the conditional is true. The second example on the left side - the return statement - will get an implied semicolon, causing it to return null every time.

The examples on the right side show the same statements with the left brace on the same line as the control statement. This pattern is the One True Brace Style, and not only does it offer more clarity for the reader, it actually works the way you would expect without inserting semicolons where they're not actually present in the code.

Because of the potential for confusion, not just of humans but the computer as well, always use the One True Brace Style. If not, you may lose your head.

I have a friend - a JavaScript engineer - who is fond of the saying that there are always at least two developers working on a project, you and the developer you will be in six months. I know I look back at code I've written six months ago and say to myself "what were you thinking" or not, as the case may be. Was I confused or tired? More often than not I say to that other developer - me from six months ago - "I suppose you think that was terribly clever" and I think if I only had added comments in I would know just what was going on in the head of that other developer - the me from six months ago.

Comments, though, are only helpful when they're present, and it would seem that a lot of us don't really want to put them in. As a senior engineer at PayPal, one of my tasks was to perform technical interviews when there was a new candidate. I was surprised at the number of people who responded, when asked about comments, that they write self-documenting code. I was often a bit like Inigo Montoya - I don't think that means what a lot of developers think it means. Self-documenting code is code that is written with precision and a measure of clarity. Both of those are qualities of good code, but they are not enough.

You should never assume that self-documenting is enough, because as the six month older me can verify, it's not. It's not enough. Put comments in, and when you're adding comments, you'll want to keep two things in mind. First, always use the whack-star pattern, even for single-line comments. I cannot count the number of times I've seen otherwise beautiful code mangled by a minifier because someone used a whack-whack and a large portion of code that should not have been commented was. As an added bonus, if you use the whack-star pattern and combine it with a whack-whack while you are developing, you can comment and uncomment large blocks of code with the insertion or deletion of a single whack - which in our example would go on the line just after the function declaration before the whack-star, commenting or uncommenting the console.log statement. The second thing you'll want to keep in mind is to use the JavaScript version of JavaDoc - JSDoc. Not only does this offer clarity to your comments and code overall, the syntax is shared among the Java community and it eliminates the need to maintain API documents as a separate project.

The clarity offered by the inclusion of comments is simply too significant to ignore. Clear, precise comments will also help you organize your code and make that organization plain to other developers working on the project - even what that other developer is you. For these reasons, I've added "use comments" to the list of principles as item number four.


Not long after I started at PayPal, we found a bug in the checkout process. It was especially difficult to root out because all the tests in development passed and all the tests in the QA sandbox passed, but when we went to production things just didn't go quite as we expected them too - there was evil there that did not sleep.

Part of the difficulty in diagnosing the issue was the nature of web sites between development, quality assurance, and production. There are resource intensive features - like analytics - that we don't want on development or QA boxes and sometimes that means our production environment is best described the way engineers used to describe aircraft - a collection of parts in close proximity moving quickly in the same direction. If we add poor coding practices into that particular mix, the risk of failure is significant.

In our case, the error was eventually traced to a variable in our analytics package that was not in the proper scope. This previously unknown global variable in a dependency wrecked havoc until it was fixed. Take a lesson here - avoid global variables. In fact, as you can, avoid the global namespace altogether. Also, always use the var keyword when declaring variables - leaving it out will force the previously undeclared variable into the global scope, even if it's only used in one little function.

Third, declare variables at the beginning of the scope. Not only does this offer a little written clarity and orgnization, it offers conceptual clarity as well as it accounts for the hoisting that JavaScript does. Fourth - and this is as important as the previous three statements - call things by their name. If you'll recall, one of the elements of good writing is that it uses precise language. Calling things by their name is part of that precise language.

Fifth, and finally, define variables in the narrowest scope possible. It's not enough to just avoid global variables, define variables as narrowly as possible. Not only will this offer a degree of precision and clarity, it will help with memory management as well.

Now I'm going to combine these five steps into a single principle we can add to the list. We're going to call that principle "name and scope variables properly" and we're going to add it as the fifth item on the list.

At this point we're nearly halfway done with our list and we've still not talked directly about code - at least not more than using the var keyword - it's all been about the softer elements like style.

We've come quite far, though - all the way to Dagobah. Master Yoda - ever encouraging and training Jedi. Of course we know he's in the Star Wars universe and we're in the JavaScript universe, because for us there is a try - and catch - and finally - and we need to use them.

The try statement will be one of your best friends. Gone are the days when it wasn't supported - I believe WebTV was the last user agent that didn't handle it - so feel free to use it any time it's appropriate. It can be especially helpful when you have dependencies and you need to minimize the risk associated with them, because you can catch exceptions thrown when those dependencies are not present.

The try statement also gives you the ability to further customize your user experience. Within the catch statement you can determine the kind of exception thrown by using the instanceof operator as shown on the slide. One word of warning - you may see examples where the exception type conditional is wrapped in the parentheses of the catch statement - don't use that practice - it's not supported. When testing the exception, use the pattern shown here. If you wish to dismiss the exception, use ignore rather than err as the parameter name. It offers a degree of clarity that is also recognized by most linters.

As our sixth principle, then, we are to do the opposite of what Master Yoda says and use try - and catch - and sometimes finally. Speaking from experience, it really will save the user experience or, at the very least, allow you to fail somewhat more gracefully than you would otherwise.

Next we'll have a word about data types.

JavaScript is a loosely-typed language, which means the data type of a variable is not declared. As expected, sometimes engineers have difficulty with the lack of precision that typically accompanies loosely-typed languages, and the lack of strict types been one of the arguments engineers have used against JavaScript in the past.

Concerns about the lack of precision and clarity in loosely-typed languages seem reasonable. After all, you wouldn't want a doctor type if you needed an engineer, or vice versa, and we all know the difficulty Bones had - he had to remind Captain Kirk countless times that he was a doctor type and not some other type.

So let's take a look at a function - one that will be used again as we progress through our list - and see how it might instruct us or what we can glean from it to add to our list.

First, you'll likely notice that there are no comments - if only there had been comments we might have a clue what it is we're look at. Fortunately for us, it's self-documenting code, so we can see that the foo function is looping forward through a list of some sort - from the syntax it appears to be an array - and changing a property on each element of the array that's an object. Seems simple enough - there shouldn't be any problem at all, right?

Except there might be. Notice that on line seven we check to make sure the element is an object. We do that because we're accessing a property - in this case className - on line eight and if the data type of the element were say a number or boolean trying to access the className would likely raise a TypeError exception. Are there other types that would raise a TypeError exception? Sure - a null value would - but that's not an object, right? Unfortunately it is - the typeof operator returns object when the type is null. Line seven will have to be fixed.

Any other problems? As I mentioned earlier, it looks like the list we're using is an array, but we have no comments that tell us that and there isn't a type check to enforce that, we're just going by the square bracket used to reference items on the list. Look at lines twelve and thirteen. Using those lines we can see that the list we're getting is actually a NodeList, which is a live collection. Looping forward through a live collection incurs a significant risk of infinite looping…but there is no way for the developer who wrote the foo function to know that the developer who wrote the function call is going to pass in a live collection, and the developer who wrote the foo function didn't give any clues to the developer who wrote the function call that an array was expected.

Ultimately, we can see that this code is not nearly as precise as it should be. The engineer writing the foo function could have used item instead of square brackets, or alternatively checked the type of the list variable to ensure it was an array. The engineer should also have checked for other types rather than just relying on a type object before modifying properties. You must always keep data type in mind, otherwise your code is prone to serious errors - errors that will often be very difficult to find and correct.

The I, Mudd episode of the original Star Trek series is one of my favorites - mostly because of its use of logic, but also because of the phrases that seem to belie the seriousness of the situation - phrases like "we seem to be taking an unscheduled ride" - it's rather like "oh, it appears we've been taken hostage and may die, but at least there's tea". Infinite loops - like those triggered by looping forward through a live collection - are the unscheduled rides of JavaScript. They're a little humorous in that they're usually brought on by a careless mistake but they can really ruin your day.

I mentioned that we would return to the foo function, so let's do that now - but let's make some corrections to it in an attempt to fix the issues. First, we'll correct line seven so that we'll catch a null value that would raise a TypeError exception - we can do that by putting a truthy check in there. Next, we'll set the loop up to start and the end and loop backward to the beginning - if we're looping through a live collection or an array that's the safe way of doing it. We'll set the index variable to the length of the list and change our for loop into a while - it's faster anyway so bonus there. Now we're all set to go - we've modified the code so it's flexible enough to handle live collections and arrays without blowing up.

Sort of. There's a potential problem in our while loop, associated with the fact that we're using the index value - a number - in a truthy check. A zero value is false, but all other numbers are true - which means negative numbers are true. We're using a decrement operator on the loop index to move backward, but the operator is in front of the variable name rather than behind the variable name, meaning the decrement is performed before the variable is evaluated. If the list length is zero, the index value is negative before it's evaluated the first time, so the truthy value is true and continues to be true as the index is decremented, and your unscheduled ride is on in earnest.

There are ways we can compensate for this - ways we can avoid the unscheduled ride, but it's the simplest way that also adds clarity without losing precision in the language - and that's to avoid confusing operators, which you'll notice is now the eighth principle on our list.

You'll recall that our while loop in the foo function - while decrement index - used a number that was decremented before being evaluated and as a result, the negative number was treated as true and sent us into an unscheduled ride. This is ultimately because not only is JavaScript loosely typed, but it's also what I call type fluid. Variables change data types in one of three ways: they can be converted, which requires an explicit function call; they can be explicitly coerced, which typically doesn't use a function call but instead uses a clue or hint that we want the variable coerced; and they can be implicitly coerced, which is when one data type is directly treated as another type.

Other languages give the ability to convert between data types; however, JavaScript goes beyond that. In fact, it will often coerce values even when we are neither aware the value will be coerced nor want the variable coerced. In a sense, it's as if JavaScript says "we will convert your data type to our own, resistance is futile".

So let's take a look at a simple variable statement and see where the potential problems lie and use that to determine what principle we should follow to write good code.

Here you'll see we have the value for PI as a string in scientific notation. We then convert that string into a number using two different methods - Number and parseFloat - both returning a floating-point value, before we attempt to convert the value to an integer using parseInt or coerce the string using the plus and minus operators and finally coerce it from an ordinary floating-point to a fixed precision number.

Notice that four of those statements are identified as potential problems.

Let's start with the first potential problem - parseInt. One might assume that the number would be converted to a floating-point then converted to an integer; however, that is not even remotely the case. The conversion reads the string starting at the left and moving right to the first non-digit. Everything in that substring - here '0314' - is then converted to an integer. There's a hidden gem in this particular conversion method, however. If the left-most character in the string is a zero, the parseInt function - which has an optional radix parameter - may default to octal and convert 0314 to the integer 204. Suddenly, though you were expecting three, you have the number 314, or possibly 204.

Next, we look at the plus2 variable. In this instance, we have two different data types - string and number - but the code is not converting either of them; the code is, however, explicitly coercing one of the values - the question is which value will it coerce.

As you can see, the two was coerced to a string data type and added to the existing string, giving us a much different numeric value - one that is a mere fraction of the value of PI.

While I would like to be able to give a hard and fast rule that says the plus operator will always concatenate strings first - that it will coerce a number to a string and then concatenate it - it's not that simple. If the plus operator is at the beginning of the variable name without white space between the plus and the variable name, the value will be coerced to a number before other operations are performed. This is true even if the value is a boolean - which is a one when true and zero when false after it's coerced.

Next, let's look at the minus2 variable. In this instance, we again have two different data types - string and number - and the code is not converting either of them. The difference between this variable and the plus2 variable is the use of the minus operator in place of the plus operator.

We might assume, given the behavior of the plus operator in the plus2 variable, that the result would be the value of the pi variable with the two removed. Of course that is not the case - the minus operator does not split a string or perform any sort of substitution on a string variable. In this case, pi is coerced to a number and two is subtracted from it. You'll notice, however, that when the pi variable is coerced, the value is different - it's not 3.14. If you're checking equivalence of coerced values, you will likely be surprised.

Finally, let's look at the asDollar variable. Of course you would not be very likely to request a precision of eighteen when referring to a dollar value; however, this example is intended to showcase a particular problem. You may think, especially given the name of the function being called - toFixed - that you are simply requesting a specific precision, but you are not. If you'll notice, the string data types on this slide have been identified by, one, being enclosed in single quotes and, two, using an italic typeface. The value for our asDollar variable is enclosed in single quotes and uses an italic typeface. You thought you were asking for a fixed precision number, but what was returned was a string.

Coercion, both implicit and explicit, is problematic. It, at the very least, lacks clarity and precision. Because of the severity of the errors that may be introduced, I've added the principle "avoid coercion" as the ninth item on the list of ten principles.

With the ninth item having been added to our list of ten principles, it's clear that we're near the end, and at this point we're going to leave code behind.

After we've followed all nine principles, and we have well-commented, self-documenting code that is precise in language and structure it'll work without a problem, right? We can have total faith that what we've written will do just exactly what we want it to do the first time and every time. That kind of faith is fine with Lord Vader - who finds a lack of faith disturbing - everyone else wants you to test your code, then test it again before you test it again. Write and run every unit test you can think of and test cases you think are highly improbable, because especially if you do the amount of business that a company like PayPal does - which was nearly five billion transactions in 2015 - you can be surprised at just how often the highly improbable happens.

In addition to running every unit test you can think of and several you hadn't thought of, be sure to use a linter to verify your code - jshint, jslint, and eslint are all very good and all do basically the same thing but in different ways. Each of the three has its own interface and can be integrated into the development process at a different point. If you wish to use all three, that can be done - but it's a little overkill. I would suggest that you integrate a linter with your version management tool, and while I have no direct experience with it, I understand having a linter integrated with your IDE makes life significantly easier.

Third, minify your code and test again. Be sure here you're using the same aggregation and minification process you use when rolling your code out into production. Each process has its own way of accomplishing the task and each can introduce something special into the mix that will break your code. I've seen beautiful code mangled and crushed into an inoperable state by aggregation and minification.

Fourth, perform code reviews. Here's something else we tend to get a little bit wrong much like we do with the expression "practice makes perfect". Typically, senior team members review code before a pull request is approved to verify that the code is sound and adheres to whatever standards exist within the organization. Those are good criteria; however, code review should not stop there. Code review should include the most junior, least experienced engineers in the group. The practice of heavily involving junior engineers in the code review process gives them the opportunity to learn to code better - just like reading good writers makes a writer better - and it gives the authoring engineer confirmation that their code contains the elements of good writing. If your code does not have the clarity to be understandable to the least experienced engineer on your team, it is not clear enough. Here I should point out that the junior members of your team need not know how to code a solution to every problem - if that were the case they would likely be senior engineers - but they should be able to understand the solution they are reading.

Fifth, as part of this process, have a human test your peer-reviewed, unit-tested, linted, minified code. This step is extremely important for any JavaScript intended for a user-agent even though it may be decidedly less so for code that runs in Node. Basically, any time a human meets the code - whether that's in a user-agent or on the command line - test the interaction. Humans have quirks and habits that help them generalize experience and reduce cognitive load that will affect how they interact with the code. Simply put, in general, no two people will interface with code the same way. There will a lot of overlap, to be certain, but it's the edge cases that you're testing here - all those behaviors that are especially active when someone is interacting with a new problem - all those things that are highly improbable.

All five steps in this process have one thing in common - that one thing that Lord Vader finds disturbing - they show a lack of faith. We need to remember as engineers, however, that our realm is not what Han Solo called a "hokey religion" - our realm is one of facts and data and requires proof. Show a lack of faith in your code and prove that its good code and good writing.

So there they are - ten principles that not only help you avoid some of the most common pitfalls, but principles that will help you become a better writer as you make their implementation habit. Follow them, and you'll discover that not only does the computer understand your code, humans do too.


A Special Note

This is the extended version of the Beyond the UI session I delivered at the American Express Mobile-Web DevCon on 28 September 2016.

Friday, August 26, 2016

Free Rum

People have asked me what has helped me debug nasty, not-so-easily-reproduced bugs and nearly always the answer is "exhaustive testing"...but what about when it isn't. Ok, most of the time it really is exhaustive testing. Of course, I make it a habit to write code to handle all different data types even when I'm 99.999% sure it will always only be one data type, because when you have 100M+ users using your code daily you'd be surprised how often 0.001% is.

So, how do we debug issues that seem to only occur 0.001% of the time? Obviously we're not talking about those use cases that fall into within the "normal" range, we're talking about outliers - or what I refer to as the oddball case. Here we're talking about those times when all our unit tests pass and still our code fails in the "real world" where there are a few cases - extreme corner cases, admittedly - when users are experiencing a "sub-par visit". These instances can easily bore a hole into our confidence (and ego...it's a little bit ego), leaving us scratching our head in confusion and frustration. What do we do then?

As with any good pirate, the answer is RUM, and lots of it!

Go ahead, start making your own pirate references and talk like a pirate...I'll wait...and I'm pretty sure I can hear you singing....
"Fifteen men on the dead man's chest —
...Yo-ho-ho, and a bottle of rum!
Drink and the devil had done for the rest —
...Yo-ho-ho, and a bottle of rum!"
Robert Louis Stevenson, Treasure Island

Of course in our case RUM does not refer to the pirate's beverage of choice but refers, instead, to Real-time (or sometimes Real) User Monitoring. The emphasis here, obviously, is on user monitoring, not testing or assuming what might be happening, and it's different than synthetic user monitoring, which is a simulation (and typically done as part of a comprehensive testing plan) because it uses real people in real-world situations.

This last point - that it uses real people in real-world situations - cannot be stressed enough. Why? Because, in the specific situation this post addresses, our software engineering has begun to move away from how people have evolved. People typically solve problems in a linear manner - it's how we've evolved. C came about because A and B happened. We make our selections in a store, go to the checkout, and pay. We don't suddenly jump out of line to go to the bank and apply for a credit card and expect to return to our place in the line with our basket full of our selections. For a very long time, our software matched this model exactly, or very nearly so. Oh, we might have a decision point where we would loop back into a process, but it was still a linear process. Most of the time, this works well, but as anyone who's stood in a queue hoping to order food only to find the customer ahead of them hasn't quite decided what they want knows, sometimes there are problems with synchronous, single-thread experiences.

We tried to resolve the synchronous, single-thread problem by adding threads. This often works alright, for the most part, but as we discovered, multiple blocked threads are not really any more productive. The answer, then, was an asynchronous (non-blocking) approach. Now, here we are, years later often suffering in callback hell and struggling to debug software because our linear, synchronous experience no longer applies to development of asynchronous systems...and as was mentioned earlier, that's why RUM enters our toolkit.

There are, of course, many ways to implement (or pour) RUM. If you're running any one of several traditional web servers, IIS or Apache, for example, Splunk is a good choice. I've written a proxy server for a Splunk app and reviewed a couple Splunk references - Splunk Developer's Guide and Learning Splunk Web Framework - so I'm not without respect; however, the downside of Splunk is that it can become expensive. For this reason alone, even if your operation uses Splunk in the production environment you may choose to forego it as a support for research and development.

As a no-cost alternative, however, you can pour your own RUM if you're using a node.js server. That's right, I said it - no-cost and RUM together - FREE RUM - (part of) every pirate's dream. Since it's relatively easy to do, and as long as you don't do something really boneheaded, you can build it securely, hoist the Jolly Roger, talk like a pirate, and follow the map below. Be warned, I'm not pointing out all the dangers (like how you can expose private or confidential information) - there are a few (fairly obvious) pitfalls, but this should be enough to get you in the general area of the treasure you seek (and I should add that you can find a more complete example/prototype in my rum github repo - https://github.com/hrobertking/rum).

First, you'll need to assemble a crew and put them on a ship. Do that by installing the socket.io module, adding it to your server module, and binding it to your httpServer instance.


Server-side JavaScript (Socket instantiation)

var server = http.createServer(handler),     io = require('socket.io')(server);

You should note that the server need not be the native node.js server, it can be an extension of the node.js httpServer object - e.g., an Express instance.

Now that you have a crew and ship, decide when you'll raise the Jolly Roger - do that by emitting an event through the socket and passing an object into the event, e.g., io.emit(event_type, event_object);.

The event type is a string literal so it can be named (nearly) anything and you can emit different events at different times, as in the example below.


Server-side JavaScript (Event Handlers)

var msg = {   id: unique_id(),   req: request,   res: response };   msg.req.on('end', function() {     msg.action = 'request';     io.emit('message', msg);   });   msg.res.on('finish', function() {     msg.action = 'response';     io.emit('message', msg);       if (msg.res.statusCode !== 200) {       io.emit('http error', msg);     }   });


Now put the spyglass to your eye and scan the horizon. Your spyglass is going to be a static page that uses the socket.io client script (https://cdn.socket.io/socket.io-1.3.5.js) and instantiates a socket. That socket will then be monitored and your event handlers will run when the event comes over the socket.


Your 'spyglass' document

<!DOCTYPE html> <html lang="en">   <head>     <meta http-equiv="Content-Type" content="text/html; charset=utf-8">     <style type="text/css">       .request { background-color:red; }       .response { background-color:yellow; }       .request.response { background-color:green; }     </style>   </head>   <body>     <script src="https://cdn.socket.io/socket.io-1.3.5.js"></script>     <script>       var socket = io();             socket.on('message', function(obj) {           var node = document.getElementById(obj.id), cls;           if (!node) {             node = document.createElement('div');             node.id = obj.id;             document.body.appendChild(node);           }           cls = node.className.split(' ');           cls.push(obj.action);           node.className = cls.join(' ');           node.innerHTML = '<p>' + obj.req.url + '</p>';         });             socket.on('http error', function(obj) {           var node = document.getElementById(obj.id);           node.className += 'http-error';           node.innerHTML += '<p>' + obj.res.statusCode + '</p>';         });     </script>   </body> </html>


Now, as you watch the 'spyglass' document in your browser, when the 'io' events are fired on the node.js httpServer they will be handled in the handlers specified in the spyglass.

Now you have insight into the important pieces of code, not as you test them (because you can get that elsewhere, like the Chrome dev tools), but as others use them, and it's debugging in those real-world situations that takes our development to the next level in our drive for results. Now, go get some pirate booty.

Happy coding.

Thursday, July 14, 2016

Go Splunking

See the forest *and* the trees

There are more than a few analytics packages out there, and some of them give you pretty decent insight into business operations – called Operational Intelligence. There are a lot of reasons why C-level executives (and even those lower on the food chain) would want that insight into business operations. Our problem (or opportunity) then, is that when we (as UI engineers) are faced with presenting that Operational Intelligence in a dashboard, what do we do?

For this post, I'm going to focus on Splunk for a few reasons. First, it's pretty widely used – most people familiar with business analytics have at least heard of Splunk. Second, building stuff for Splunk is a lot simpler than it seems at first glance, as you'll see if you keep reading this post. Third, I have a personal relationship to it – at least two of the four companies I've worked with in the last five years use it and I've been privileged to review multiple tech books about it over the last five years, which has let me experience it through others.

Two of the most common approaches when developing dashboards or apps for Splunk are using Splunk's Simple XML and using HTML, CSS, and JavaScript on the Splunk server to develop the apps everyone wants. There's another option though, and it's the option I would suggest – develop the app on a completely different server.

Developing the dashboard or app on an non-Splunk server lets the Splunk server do what it's really meant to do – index data and provide a query interface to the indexed data – and lets another server handle user requests and serve up the adaptive, responsive web pages more easily and consistently. In addition to resolving potential performance and maintenance issues, this also enables you to create web pages that comply with all the web accessibility guidelines easily (which is something Splunk isn't great at, to be honest). If the tools you use to develop your Splunk dashboard/app are the same tools you use for your other web apps, there are even more benefits (such as possibilities for code re-use).

Here's a quick and (admittedly) overly simplistic explanation of how to get started and have a basically free server that responds quickly and keeps security in mind.
  1. Set up a web server using node.js
    For this you can use something like Express, but you might also develop your own. If you decide to develop your own, feel free to look at my node-experiments github repo at https://github.com/hrobertking/node-experiments. You'll want to use node.js for this (rather than using Apache or Nginx or something else) for reasons that will be revealed in the next step. For the purposes of this blog entry, I'm going to refer to this web server (which should really be dedicated to your Splunk apps) as the Splunk App Portal.
  2. Add the Splunk SDK (JavaScript version) to your toolkit
    The Splunk JavaScript SDK requires node.js for server-side scripting. Of course you can install it easily (npm install splunk-sdk) and then use require in your script to access it. As part of adding the SDK to your toolkit, be sure to visit the Splunk>dev JavaScript portal (http://dev.splunk.com/javascript) to see the SDK documentation, including examples.
  3. Instantiate a Splunk Service object
    Here's the relatively easy part
    var splunkjs = require('splunk-sdk'),   service = new splunkjs.Service({       host: 'my_splunk_server',       password: my_splunk_password,       port: 'my_splunk_server_port',       scheme: 'https',       username: my_splunk_username,       version: '5.0'     });
    Note that you should not ever code a username and password in a JavaScript file. If you pay careful attention to lines 4 and 7 you'll note that the values are not enclosed in single quotes – they are variables. Put in a little extra work and set the value of those variables from the command line. Using this approach enables your newly created Splunk App Portal to communicate with the Splunk server in a controlled manner. I also recommend establishing a Splunk account specifically for this purpose so that use can be monitored and controlled with greater granularity.

    I should point out that if you're using JavaScript to develop apps for Splunk another way, you're most likely adding the config.js file and calling the config method to pass in the username and password. It should go without saying (but won't) – don't hard code the username and password in JavaScript file. If you're doing something like the following, stop and fix it.
    <script src="MY_SPLUNK_FILES/splunkjs/config.js"></script> <script> splunkjs.config({     host: 'my_splunk_server',     port: 'my_splunk_server_port',     scheme: 'https',     authenticate :{       username :'DoNotDoThis',       password :'NoNotEver'     }   }); </script>
  4. Call the oneshotSearch method to get your data
    Calling the oneshotSearch method is fairly straightforward, code-wise, anyway.
    service.oneshotSearch(query, params, function(error, results) {     //your rendering instructions go here   });
    Here's where it gets a little tricky. The query argument will be something like 'search index=myindex'. If you have even the slightest experience with Splunk, that query string will look familiar. You can, of course, use all the Splunk functions and so forth to craft your search string, just keep in mind that simpler searches are better. The params argument will be a JavaScript object that contains properties such as earliest_time and output_mode – such as var params={earliest_time:'-4h', latest_time:'now', output_mode:'json'};. I recommend using JSON as the output mode (though there are other modes) because it will be easier to reference when you render the response.
  5. Render the response
    This is where the real magic happens. If you're looking up values – let's say you need to convert a location code like ATL or ORD to an actual longitude and latitude – this would be the place to do it. This is also where you will decide how you're going to format the response – whether it be HTML, JSON, XML, or even plain text. If you're going with HTML, you may want to consider using a templating engine (like dust.js or mustache.js). Using a templating engine means your response can be even more flexible, and using something like Adaro and Makara (see http://krakenjs.com/) gives you even more power.

Of course, using this approach (rather than Simple XML) means you'll have to actually write more of the web page(s), but you'd likely have to do most of the writing in any case. As is noted in the fifth step, if you're using dust.js or another templating engine, it's going to be pretty easy in general – and it will likely be even easier if you're rendering the response as JSON, where your Splunk App Portal is acting as a proxy for the Splunk server. Why might you want to do this? For many of the same reasons you might want to control data coming out of your database – most notably, who gets to see what. Separating functionality in this manner also means the systems are simplified, or at least simpler than combined systems. Since complex systems fail in complex ways, we're avoiding that trap as well.

Overall, even though this is an admittedly simplified explanation, this is a relatively easy process – a process that will likely benefit you in terms of both performance and maintenance once you have established the infrastructure to support it.

Since this is a fairly complex topic and I've not given much detailed information, if you have specific questions about the process or how to do something within this model, feel free to add them in the comments below and I'll address them as soon and as completely as I can.

Happy coding.

Wednesday, March 4, 2015

Time is a river of events, and strong is its current

Time is a river of events, and strong is its current;
no sooner is a thing brought to sight than it is swept by
and another takes its place, and this too will be swept away.
~ Marcus Aurelias ~
It is doubtful that one can survive in today's software engineering environment without an understanding of asynchronous, event-driven development, and that's especially true for web developers. It's seems a little difficult to believe, but we've had AJAX for more than 10 years, and for the last 6 years or so we've had a very powerful asynchronous server-side tool in nodejs.

Is being asynchronous all it's cracked up to be, however? You may be asking yourself, if I'm just building a tool that does one thing, and I know the order in which the tasks need to be done, why not just use synchronous code...and that is a really good question. Let's take a hypothetical journey and see how easily we navigate this river of time using a real-time approach.

Let's say I am building a website. To keep costs low and security high, I'm going open-source and using Apache as my web server and I'm using Apache Sling™ to manage my content. Now I can easily build a single website and get it working without a problem; however, my use case requires that I set up thousands of 'child' sites - one for each of my local offices. Since this is a hypothetical, we don't need to bother with what sort of product is being offered - it could be an educational institution with satellite offices or a religious institution, for example - we just need to serve each local 'office' as it presents different hours, a different location, and offers slightly different services.

I can roll this whole parent-child monster out by creating the right architecture - a master template with child templates and specialized content. Doing this manually is feasible on a very small scale, but quickly becomes something that cannot be managed easily. One possible solution to this dilemma is for each office to be responsible for building their own custom site using the master site we set up; however, a significant amount of education and pre-configuration would be required to make this option a reality, as each office will need either dedicated attention or an in-house 'expert'.

Luckily for us, Apache Sling™ is itself built on a ReSTful framework, so all we need to do is gather the data for each of the offices and then use curl or some other utility to generate the correct HTTP commands to create the site, pass in the data to update all the special values, and voilĂ  - we build a website in less time than a human can even react to a signal. Easy, right? Not so fast.

When a person is using the interface to create the website, then going through and changing the content, there is a lower limit on the time it takes to perform those activities. Assuming the web server responded instantaneously (which we know is a fantasy itself), there still would be a response and hundreds of milliseconds between requests. What happens when a tool, like a team of paddlers in a raft, issue the HTTP requests too quickly, purely asynchronously without waiting for a response? There are a few possibilities - the web server starts seeing your attempts at creating and updating content as a DoS attack and responds accordingly, or it doesn't respond distinctly to a DoS attack and is overwhelmed, or we have a race condition between the requests. All of these possibilities leave you without a site at the end of the process, and possibly with a non-functional web server. As a Dungeon Master might say, "the stronger and faster among you paddled fiercely, spinning your boat in circles as the strong current of time washed away your boat".

What is needed in this case, is a tour guide who can tell those who are propelling the boat when to paddle and where. Let me demonstrate this idea by addressing the hypothetical situation by building a nodejs application that will create the website, then update the content, and finally, declare success. In order to do this, I'm going to use the asynchronous request (initiated by request method in the http library) to enable our "tour guide" and navigate the hazards by emitting an event (using the EventEmitter from the events library) after we've handled the response.

But...but...but...I heard that building anything synchronous in nodejs is wrong, and this sounds synchronous. Yes, in the application sense this basically turns asynchronous commands into a synchronous process, but only somewhat, as it's really more a synchronized process, not synchronous. After all, our tour guide doesn't need to know what else is going on downstream or what's going on under the water or what other rivers are like - they only need to know how to navigate this hazard on this river to get out safely on the other side.

Beside the fact that this is more a synchronized process than synchronous, we must admit that many things in the real world rely on being at least somewhat synchronous. For example, how can we know if we can update a profile unless we know the profile exists or is created or how can we know if we can ship a product unless we know we have it? We can't. Does that mean for all of these synchronous activities we cannot use nodejs? Poppycock. Yes, there is great power that comes with asynchronous processes - but that perception of power is because we assume the processes can be run in parallel. I could insert the old joke here about nine women having a baby in one month, but we all know the reality - we all recognize that there are some processes that cannot be run in parallel.

Another way to look at this is that sometimes, we lose focus and forget that while our single boat is navigating the river there are other boats and other rivers. If you're really concerned about performance, build your app in such a way that all boats on the river travel the river safely at the same time, even if each boat has to navigate from point to point.

Back to our hypothetical...a simplified portion of the code for this might look like...

function doNextStep(response) {
  if (response.status_code === 200) {
    switch (response.step) {
      case 1:
        doStep2();
        break;
      case 2:
        doStep3();
        break;
    }
  }
}
function doStep1() {
  // create the site
  destination.step = 1;
  sendRequest({host:myhost, path:'/bin/wcmcommand', port:4502}, destination);
}
function doStep2() {
  // update the site
  branch_data.step = 2;
  sendRequest({host:myhost, path:'/' + childsite, port:4502}, branch_data);
}
function doStep3() {
  // log the results
  logResults(branchData);
}
…
function sendRequest(options, data) {
  var req = http.request(options, function(res) {
    var body = '';
    res.on('data', function(chunk) {
        body += chunk;
      });
    res.on('end', function(err) {
        try {
          data.response = JSON.parse(body);
          emitter.emit('step_done', data);
        } catch(err) {
          console.log(err);
        }
      });
  });
  req.write(data);
}
…
emitter.on('step_done', doNextStep);

Of course you could use something like a timeout to build in human-like reaction times, and that might work for most of the situations, but the problem here is generally not on the end issuing the HTTP requests, it's with the end receiving the requests and processing them. We need something that watches for the response instead of waiting for a response, and this is why the callbacks on the asynchronous methods were built. Like a tour guide, the emitter calls out each time we've gotten a response and are ready to address another hazard as we've finished with the last.

In this example, we've created a river of events that our tour guide navigates, and in our hypothetical, synchronized process, it would be conceivable that we could set up a nice website in less than 200ms. The difference in speed of a (long) 200ms synchronized process compared to a human doing the same task makes me care less about whether or not something meets my anti-synchronous ideology.

Happy coding.