Data Bending

uistory

We respond to data differently depending on its presentation.

A tightly filled table with sprawling labels and an endless depth do nothing to engage the viewer, and if the contents are foreign enough, you’ll find a user lost in a sea of confusion. There exists various ways to transform data into living, breathing entities. We can colorize, animate, and build the interface in ways that help convey the insight portrayed within. Flow is also important. We need to think about data in relation to the user story and how it contributes to the application as a whole. If all of this information is at the forefront, it needs to be engaging. First impressions matter.

Thankfully, good design decisions make all the differences in the world. You’ll convert new users who share the same data-driven appreciation. In a world brimming with I/O, it has never been more important to process data in meaningful ways.

Data is becoming more intimidating, and its never-ending volumes can present tricky problems. In order to obtain appropriate information from massive amounts of data, we utilize machine learning techniques. Researchers in this field investigate the ways in which programs can “intuitively” consume data on scales so massive it would be impossible otherwise. The amount of data humans and programs output each year have become too large to consume and it’s becoming vital to deploy programs that teach themselves the filtering process. Unfortunately, machine learning is beyond the scope of this post, and perhaps this entire blog. We will focus instead on the steps succeeding a successful data extraction.

uistory2

Developing mean visualization skills require a bit of patience, and small, data-driven projects are the way to go. Once you’ve extracted the necessary information, it’s onward to finding an optimal way to present it. There are a myriad of methods a developer can take, but the main concern is app functionality. Who’s the audience? What’s the user story? Hopefully, you’ve had enough time to think through these questions. There are times when presentation of the data matters less, especially when the end user has no need for such levels of analytics. A recipe application does not need ten pie charts examining the various hours in which the user cooked with sugar instead of salt.

But then there are occasions where beautiful data presentations are vital. Is your extracted data telling a story? Do you depend on the data to construct a bridge between the user and some complex analytics? If you need some hits of inspiration, head on over to the New York Times Interactive and see how the visualized data brings another dimension of depth and context to its articles. Examine some effective designs and ask yourself about the effectiveness of the data being presented. Could it be better, or worse?

uistory3

Now that you’ve had some inspiration for visualizing data, you can dive into a wide array of tools made just for the task. Do you speak Javascript? Try heading over to D3.js and play around with the sample code until you get a feel for the various configurations. There exists a large amount of tools out there, each facilitating the creation of visual data. Find a few that you enjoy working with, and build a few toy projects with them.

Embrace the overload of the information age and learn to swim through its currents, and you’ll be well on the way to transforming ordinary stats into captivating statements.

Advertisements

Your promise is awaiting…

Promises solve a lot of issues that callbacks trip over, helping to clean up readability by avoiding callback hell and endless callback jumps. They also empower us with more control over asynchronous code, providing .then and .catch blocks. Even so, there are still times when these wonderful little tools falter.

Have you ever tried implementing a series of complex conditionals inside a Promise chain? It becomes quite ugly. You might end up with multiple nested promises, perhaps even six, or seven layers deep. Sprinkle in a few if and else statements, and you’ve got a recipe for disaster.

You could flatten those nested Promises so that each .then block returns a new Promise. Even then, you’d be dealing with a large number of chained Promises. Even then, it’d still be messy to keep track of return values on the tenth Promise block. What if you had to keep track of every value returned in every single one of the blocks?

function showUsers {
   return findUsersFromDB
     .then(users => {
       if (users) {
         processResults(users)
           .then(attr => {
              // keep going!?
             return attr;
           })
       } else {
         // we love nesting!
       }
     })
}

One option would be an object that is passed through each .then block, gathering information along the way. Another option would be a global object that every block has access to. Both are acceptable, but come with their own downfalls that may eventually trigger bugs that are extremely hard to squash. Globals can easily be accessed and changed, while passed objects can become tricky to track in deeply nested blocks.

Thankfully, ES2017 comes with a few tricks up its sleeves. Async functions are a feature currently implemented in Node 8.x, and help alleviate a lot of the problems encountered when one solely relies on Promises and/or callbacks to handle all the heavy lifting. What’s even cooler is the fact that an await function returns a promise itself!

So what exactly is an async function? It is syntactic sugar built off of the backs of generators and promises (quite interesting to see an await function’s behind-the-scenes). An in-depth explanation is beyond the scope of this post, but simply put, it is another way of writing asynchronous code. It gives the illusion of code that looks and behaves in a manner similar to synchronous code, and provides a cleaner interface for doing so.

Here is how the general syntax looks.

async function showUsers {
   const users = await findUsersFromDB();
   if (users) {
     const attr = await processResults(users);
   } else {
     // whoo no nesting!
   }
}

It is important to note that you can only utilize .await if it’s in the same function scope as the async function. If you declared an async function with another function inside, and tried using .await in the inner function, you would get a syntax error. It’s fairly easy to stumble upon this error, so be aware.

This implementation is not a cure-all for every problem, and in some cases, you are better off utilizing Promises (concurrency). However, .await works by casting the function into a Promise – meaning anything returned from an await function can also be chained with a .then as well!

The difference between the two examples above is night and day. It is easier to read, understand, and with a small modification – debug as well. In order to handle error cases, simply wrap the contents of the async function in a try/catch block. The catch block will also send any errors encountered inside of the await function to your error handlers. By doing so, you are taking of synchronous and asynchronous code simultaneously.

It is important to understand that while async functions are a great tool to have, it may turn your code into a series of singular await functions that need to wait on each other in order to execute. Serial code. This means that the most efficient way to write async functions needing to execute in parallel is to utilize Promise methods like .all, resolving all your await functions at once.

Remember, it is important to know when your code could be running concurrently when they are currently running sequentially. Async functions are yet another set of tools that can be mixed and matched with other asynchronous coding methods, and a good understanding of generators and promises will yield greater results in one’s ability to utilize async functions.