Collective #550

Inspirational Website of the Week: Déplacé Maison A refreshing design with lots of character and perfect details. Our pick this week. Check it out Where to put buttons on forms Button placement can make or break a form. Find out the Read more

Bottom Navigation Pattern On Mobile Web Pages: A Better Alternative?

dreamt up by webguru in Uncategorized | Comments Off on Bottom Navigation Pattern On Mobile Web Pages: A Better Alternative?

Bottom Navigation Pattern On Mobile Web Pages: A Better Alternative?

Bottom Navigation Pattern On Mobile Web Pages: A Better Alternative?

Arthur Leonov



Whenever you hear of “mobile navigation”, what’s the first thing that comes to mind? My guess would be the hamburger slide-out menu. This design pattern had been in use since the first responsive design days, and even though a lot has changed since then, this particular pattern has not. Why is that?

How did we start using the top navigation with the hamburger menu in the first place? Is there a better alternative? In this article, I will try to explore these questions.

The History Of The Top Navigation And The Hamburger

The first hamburger menu icons started appearing in the ‘80s. It was designed by Norm Cox for the Xerox Star — the world’s first graphical user interface. He also designed the document icon for the same interface. This piece of history was uncovered by Geof Allday (who actually emailed Norm Cox). You can read the whole email response by clicking here. Later, it was seen on Windows 1 &
and DOS.

The current mobile navigation — as we know it — was popularized by Ethan Marcotte’s “Responsive Web Design” book back in 2011. Since then, the top navigation and the hamburger became the industry’s standard.

The Mobile Phone Screen Size Doubled In 10 Years

Since the original iPhone, mobile sales have been increasing year after year. 2019 is the first year that the market reached saturation point and the sales have started to decrease. But that doesn’t mean people are not using phones. By 2020, we will spend 80% of our time on the Internet on mobile phones, reports Quartz and Ciodive. Compare that to 2010, when only a fourth of Internet users were phone-based.

As phone sales increased, screen sizes have more than doubled, too. The average screen size of smartphones has increased from 3.2 inches all the way to 5.5 inches. In 2017, device makers started to adopt the taller 18:9 aspect ratio with 5.7-inch and 6-inch 18:9 displays. Now, we are starting to see 6-inch 18:9 displays become the new standard in flagships as well as in the mid-range price segments, as they have more screen area than 5.5-inch 16:9 displays, XDA-Developers reports.

An overview of how the mobile scren sizes have changed

An overview of how the mobile screen sizes have changed (Image source: Scientamobile) (Large preview)

Basically, the mobile phone screen size is getting bigger and bigger. That’s fine, but how do we adapt our design patterns to reflect these changes?

Thumb-Driven Design

I first heard of the term “thumb-driven design” from Vitaly Friedman. It’s based on the Steven Hoober’s and Josh Clark’s research on how people hold their devices.

The gist of it is that in nearly every case, three basic grips were most common. 49% held their phones with a one-handed grip, 36% cradled the phone in one hand and jabbed with the finger or thumb of the other, and the remaining 15% adopted the two-handed BlackBerry-prayer posture, tapping away with both thumbs, states Josh Clark. Steven Hoober had found that 75% of users touch the screen with only one thumb. Hence, the term thumb-driven design.

There are three main ways in which we hold our phones

There are three main ways in which we hold our phones. (Large preview)

In 2016, Samantha Ingram wrote an article named “The Thumb Zone: Designing For Mobile Users” which further explores these ideas. She defined easy-to-reach, hard-to-reach and in-between areas.

Thumb-zone mapping explained by Samantha Ingram

Thumb-zone mapping explained by Samantha Ingram (Large preview)

However, I would argue, that with increasing phone sizes, the mapping has shifted a bit:

New thumb-zone mapping adjusted to larger screen sizes

New thumb-zone mapping adjusted to larger screen sizes (Large preview)

When the phones were small, most areas were easy to reach. As our screens got bigger, the top part became virtually impossible to touch without adjusting your phone. From the example above, we can see where the most expensive screen real estate is. Yet, it’s often neglected on web pages. How can we fix this?

Bottom Navigation Pattern

Every now and then, bottom navigation pattern pops up on the web. The idea itself is quite simple: move the navigation bar further down.

Slack web page navigation reimagined with new thumb-zone mapping

Slack web page navigation reimagined with new thumb-zone mapping (Large preview)

Positioning the navigation bar at the bottom makes it easier for users to click on the menu icon, while secondary items can be moved to the top. Basically, you simply switch the order. Mobile apps have been using this logic with the tap bar pattern. It’s not a new idea in itself, but it’s still not as popular in web design as it is in app design.

This is not a foolproof solution since it raises a few critical questions, but it’s a worthy alternative. Let’s explore some of the questions that may come up.

Primary And Secondary Items

As the top of the screen is becoming hard to reach, placing the primary menu items closer to the bottom is a better alternative. But what about the other things that are just as important?

I propose two ideas to tackle this problem:

  1. Placing the search bar or any non-primary items to the top;
  2. CTA buttons should remain at the bottom next to the menu items as it is a vital part of the navigation.

A wireframe of reimagined primary and secondary navigation items.

A wireframe of reimagined primary and secondary navigation items (Large preview)

How Will This Affect Scrolling With Large Menus?

Some websites have extensive menus, submenus and everything in between. Naturally, there will be scrolling involved. How does flipping the primary/secondary items work in this scenario?

A wireframe of a reimagined large menu

A wireframe of a reimagined large menu (Large preview)

Make the primary and secondary items (menu link, logo, search input) fixed while leaving the menu list scrollable. That way, your users will be able to reach the critical things they need.

You might have concerns about the logo placement. There are two ways to go about it:

  • Placing the logo at the bottom might be a bit awkward, however, the thumb will most likely not obstruct it. It can be missed, though, as we tend to scan top to bottom.
  • A more reasonable option is to keep the logo at the top of the page, but not to have it fixed. Make it a part of the content so it goes away as you scroll. That way, people will still be able to see it perfectly.

As you can see, I used the menu label in the wireframe. Kevin Robinson had found that putting a label next to the icon increased engagement by 75%:

A wireframe of the logo placed at the top while the menu can be found at the bottom

A wireframe of the logo placed at the top while the menu can be found at the bottom. (Large preview)

How Does This Work With Handlebars?

Some operating systems and browsers tend to use the bottom area of the screen for their own purposes. iOS handlebars can get in the way of bottom navigation. Make sure the navigation is spacious enough to accommodate the iOS safe area.

iOS Handlebars and safe areas

iOS Handlebars and safe areas (Large preview)

If you place the logo dead in the center, the link might clash with the handlebar functionality. A bit of padding will do the trick.

Will The Users Adjust To This Pattern Or Find It Disorentating?

As I was writing this article, I kept thinking of whether this would turn out into a big redesign or a simple usability improvement for users navigating through your website. After all, according to Jakob’s Law, users spend most of their time on other sites. This means that users prefer your site to work the same way as all the other sites they’re already familiar with.

As a counter-argument to Jakob’s Law, I would like to propose Fitts Law. It argues that the time to acquire a target is a function of the distance and size of the target. Basically, the smaller and further away the target is, the higher the interaction cost. NN/g has a wonderful video explaining this in more detail:

“A bottom hamburger menu icon will have a much lower interaction cost compared to the top menu icon because it’s closer. By placing the menu CTA near the thumb, we are allowing the user to reach it’s end goal faster. Would the users find the feature disorientating if it lowers their interaction cost? Probably not.”

How Will This Integrate With The Tap Bar Pattern?

A tap bar patterns lists three to five most common first-level actions to click on a single row. You may have seen it in popular apps and some websites:

iOS Tap bar design by Mengyuan Sun
Tap bar design by Mengyuan Sun (Large preview)

Hamburger menus have sparked a lot of controversy over the years. Just take a few moments to read this article, and this one, and this one, and most importantly, this one. You’ll then understand why the tap bar became the preferred navigation pattern in mobile app design.

Nielsen argues that hidden navigation (hamburger menu) significantly decreases user experience both on mobile and desktop. On mobile, people used the hidden navigation in 57% of the cases, and the combo navigation in 86% of the cases, i.e. 1.5 times more! The combo navigation that Nielsen refers to is a tab bar pattern combined with a hamburger menu — here’s an example:

Samsung app example from Rizki Rahmat Ridha for Muzli

The Samsung app example from Rizki Rahmat Ridha for Muzli (Large preview)

It might seem like the tap bar is the perfect solution, but it has its problems too. Fabian Sebastian raised a good point that it only works on top-level views. It does not work with secondary navigation items. To solve this problem, a hamburger/tap bar hybrid was born. If you pay attention to the Samsung app, you’ll see that the last item on the menu is the “*More*” button which calls up the hamburger menu.

In essence, the bottom navigation pattern integrates quite well into the tap bar pattern if you want to combine both of them. The best place to look for good examples is in the mobile app world.

I opened up Photoshop and did a quick mockup of a few popular websites in order to explain that changing the navbar to go bottom-up is not that difficult.

Let’s first take a look at Bloomberg:

Bloomberg website with a reimagined bottom navigation

The Bloomberg website with a reimagined bottom navigation (Large preview)

Next, let’s take a look at Invision:

Invision website with a reimagined bottom navigation

The Invision website with a reimagined bottom navigation (Large preview)

Last but not least, the good ol’ Reddit:

The <a href='https://www.reddit.com/'>Reddit website</a> with a reimagined bottom navigation

The Reddit website with a reimagined bottom navigation (Large preview)

Yes, this idea does raise questions, but it’s simple enough to be adapted to the web. It does make a usability difference as the interaction cost is much lower.

That Sounds Great, But How Do I Convince My Clients?

You, as the designer, might see the potential of this pattern, but what if your client or your boss doesn’t? I would answer this problem with a couple of arguments:

  • Mobile apps have been placing valuable menu items to the bottom for years already. Just send them these two articles for starters:
  • I had noticed cases in which popular mobile apps started to shift important bits to the bottom. A good example is Uber. For them, the search bar is one of the most important items on the screen. In the old design, its position was at the top. Now, they’ve shifted it to the bottom. Could we be on to something here?

Old and new Uber search bar designs

The old and new Uber search bar design (Large preview)

Shifting important navigation items to the bottom is not a new thing in mobile app design. It’s just that — for some reason — the web industry has not caught up on this just yet.

Summary

The facts are quite clear: Phones are getting bigger, and some parts of the screen are easier to interact with than others. Having the hamburger menu at the top provides too big of an interaction cost, and we have a large number of amazing mobile app designs that utilize the bottom part of the screen. Maybe it’s time for the web design world to start using these ideas on websites as well?

I understand that all of this is not a foolproof solution for all use cases, but it’s worth a shot. It helps make the experience just a tad bit better. I’m interested in hearing your thoughts below!

Useful Reading Resources

Smashing Editorial
(cc, il)

Source: Smashing Magazine, Bottom Navigation Pattern On Mobile Web Pages: A Better Alternative?

Bottom Navigation Pattern On Mobile Web Pages: A Better Alternative?

dreamt up by webguru in Uncategorized | Comments Off on Bottom Navigation Pattern On Mobile Web Pages: A Better Alternative?

Bottom Navigation Pattern On Mobile Web Pages: A Better Alternative?

Bottom Navigation Pattern On Mobile Web Pages: A Better Alternative?

Arthur Leonov



Whenever you hear of “mobile navigation”, what’s the first thing that comes to mind? My guess would be the hamburger slide-out menu. This design pattern had been in use since the first responsive design days, and even though a lot has changed since then, this particular pattern has not. Why is that?

How did we start using the top navigation with the hamburger menu in the first place? Is there a better alternative? In this article, I will try to explore these questions.

The History Of The Top Navigation And The Hamburger

The first hamburger menu icons started appearing in the ‘80s. It was designed by Norm Cox for the Xerox Star — the world’s first graphical user interface. He also designed the document icon for the same interface. This piece of history was uncovered by Geof Allday (who actually emailed Norm Cox). You can read the whole email response by clicking here. Later, it was seen on Windows 1 &
and DOS.

The current mobile navigation — as we know it — was popularized by Ethan Marcotte’s “Responsive Web Design” book back in 2011. Since then, the top navigation and the hamburger became the industry’s standard.

The Mobile Phone Screen Size Doubled In 10 Years

Since the original iPhone, mobile sales have been increasing year after year. 2019 is the first year that the market reached saturation point and the sales have started to decrease. But that doesn’t mean people are not using phones. By 2020, we will spend 80% of our time on the Internet on mobile phones, reports Quartz and Ciodive. Compare that to 2010, when only a fourth of Internet users were phone-based.

As phone sales increased, screen sizes have more than doubled, too. The average screen size of smartphones has increased from 3.2 inches all the way to 5.5 inches. In 2017, device makers started to adopt the taller 18:9 aspect ratio with 5.7-inch and 6-inch 18:9 displays. Now, we are starting to see 6-inch 18:9 displays become the new standard in flagships as well as in the mid-range price segments, as they have more screen area than 5.5-inch 16:9 displays, XDA-Developers reports.

An overview of how the mobile scren sizes have changed

An overview of how the mobile screen sizes have changed (Image source: Scientamobile) (Large preview)

Basically, the mobile phone screen size is getting bigger and bigger. That’s fine, but how do we adapt our design patterns to reflect these changes?

Thumb-Driven Design

I first heard of the term “thumb-driven design” from Vitaly Friedman. It’s based on the Steven Hoober’s and Josh Clark’s research on how people hold their devices.

The gist of it is that in nearly every case, three basic grips were most common. 49% held their phones with a one-handed grip, 36% cradled the phone in one hand and jabbed with the finger or thumb of the other, and the remaining 15% adopted the two-handed BlackBerry-prayer posture, tapping away with both thumbs, states Josh Clark. Steven Hoober had found that 75% of users touch the screen with only one thumb. Hence, the term thumb-driven design.

There are three main ways in which we hold our phones

There are three main ways in which we hold our phones. (Large preview)

In 2016, Samantha Ingram wrote an article named “The Thumb Zone: Designing For Mobile Users” which further explores these ideas. She defined easy-to-reach, hard-to-reach and in-between areas.

Thumb-zone mapping explained by Samantha Ingram

Thumb-zone mapping explained by Samantha Ingram (Large preview)

However, I would argue, that with increasing phone sizes, the mapping has shifted a bit:

New thumb-zone mapping adjusted to larger screen sizes

New thumb-zone mapping adjusted to larger screen sizes (Large preview)

When the phones were small, most areas were easy to reach. As our screens got bigger, the top part became virtually impossible to touch without adjusting your phone. From the example above, we can see where the most expensive screen real estate is. Yet, it’s often neglected on web pages. How can we fix this?

Bottom Navigation Pattern

Every now and then, bottom navigation pattern pops up on the web. The idea itself is quite simple: move the navigation bar further down.

Slack web page navigation reimagined with new thumb-zone mapping

Slack web page navigation reimagined with new thumb-zone mapping (Large preview)

Positioning the navigation bar at the bottom makes it easier for users to click on the menu icon, while secondary items can be moved to the top. Basically, you simply switch the order. Mobile apps have been using this logic with the tap bar pattern. It’s not a new idea in itself, but it’s still not as popular in web design as it is in app design.

This is not a foolproof solution since it raises a few critical questions, but it’s a worthy alternative. Let’s explore some of the questions that may come up.

Primary And Secondary Items

As the top of the screen is becoming hard to reach, placing the primary menu items closer to the bottom is a better alternative. But what about the other things that are just as important?

I propose two ideas to tackle this problem:

  1. Placing the search bar or any non-primary items to the top;
  2. CTA buttons should remain at the bottom next to the menu items as it is a vital part of the navigation.

A wireframe of reimagined primary and secondary navigation items.

A wireframe of reimagined primary and secondary navigation items (Large preview)

How Will This Affect Scrolling With Large Menus?

Some websites have extensive menus, submenus and everything in between. Naturally, there will be scrolling involved. How does flipping the primary/secondary items work in this scenario?

A wireframe of a reimagined large menu

A wireframe of a reimagined large menu (Large preview)

Make the primary and secondary items (menu link, logo, search input) fixed while leaving the menu list scrollable. That way, your users will be able to reach the critical things they need.

You might have concerns about the logo placement. There are two ways to go about it:

  • Placing the logo at the bottom might be a bit awkward, however, the thumb will most likely not obstruct it. It can be missed, though, as we tend to scan top to bottom.
  • A more reasonable option is to keep the logo at the top of the page, but not to have it fixed. Make it a part of the content so it goes away as you scroll. That way, people will still be able to see it perfectly.

As you can see, I used the menu label in the wireframe. Kevin Robinson had found that putting a label next to the icon increased engagement by 75%:

A wireframe of the logo placed at the top while the menu can be found at the bottom

A wireframe of the logo placed at the top while the menu can be found at the bottom. (Large preview)

How Does This Work With Handlebars?

Some operating systems and browsers tend to use the bottom area of the screen for their own purposes. iOS handlebars can get in the way of bottom navigation. Make sure the navigation is spacious enough to accommodate the iOS safe area.

iOS Handlebars and safe areas

iOS Handlebars and safe areas (Large preview)

If you place the logo dead in the center, the link might clash with the handlebar functionality. A bit of padding will do the trick.

Will The Users Adjust To This Pattern Or Find It Disorentating?

As I was writing this article, I kept thinking of whether this would turn out into a big redesign or a simple usability improvement for users navigating through your website. After all, according to Jakob’s Law, users spend most of their time on other sites. This means that users prefer your site to work the same way as all the other sites they’re already familiar with.

As a counter-argument to Jakob’s Law, I would like to propose Fitts Law. It argues that the time to acquire a target is a function of the distance and size of the target. Basically, the smaller and further away the target is, the higher the interaction cost. NN/g has a wonderful video explaining this in more detail:

“A bottom hamburger menu icon will have a much lower interaction cost compared to the top menu icon because it’s closer. By placing the menu CTA near the thumb, we are allowing the user to reach it’s end goal faster. Would the users find the feature disorientating if it lowers their interaction cost? Probably not.”

How Will This Integrate With The Tap Bar Pattern?

A tap bar patterns lists three to five most common first-level actions to click on a single row. You may have seen it in popular apps and some websites:

iOS Tap bar design by Mengyuan Sun
Tap bar design by Mengyuan Sun (Large preview)

Hamburger menus have sparked a lot of controversy over the years. Just take a few moments to read this article, and this one, and this one, and most importantly, this one. You’ll then understand why the tap bar became the preferred navigation pattern in mobile app design.

Nielsen argues that hidden navigation (hamburger menu) significantly decreases user experience both on mobile and desktop. On mobile, people used the hidden navigation in 57% of the cases, and the combo navigation in 86% of the cases, i.e. 1.5 times more! The combo navigation that Nielsen refers to is a tab bar pattern combined with a hamburger menu — here’s an example:

Samsung app example from Rizki Rahmat Ridha for Muzli

The Samsung app example from Rizki Rahmat Ridha for Muzli (Large preview)

It might seem like the tap bar is the perfect solution, but it has its problems too. Fabian Sebastian raised a good point that it only works on top-level views. It does not work with secondary navigation items. To solve this problem, a hamburger/tap bar hybrid was born. If you pay attention to the Samsung app, you’ll see that the last item on the menu is the “*More*” button which calls up the hamburger menu.

In essence, the bottom navigation pattern integrates quite well into the tap bar pattern if you want to combine both of them. The best place to look for good examples is in the mobile app world.

I opened up Photoshop and did a quick mockup of a few popular websites in order to explain that changing the navbar to go bottom-up is not that difficult.

Let’s first take a look at Bloomberg:

Bloomberg website with a reimagined bottom navigation

The Bloomberg website with a reimagined bottom navigation (Large preview)

Next, let’s take a look at Invision:

Invision website with a reimagined bottom navigation

The Invision website with a reimagined bottom navigation (Large preview)

Last but not least, the good ol’ Reddit:

The <a href='https://www.reddit.com/'>Reddit website</a> with a reimagined bottom navigation

The Reddit website with a reimagined bottom navigation (Large preview)

Yes, this idea does raise questions, but it’s simple enough to be adapted to the web. It does make a usability difference as the interaction cost is much lower.

That Sounds Great, But How Do I Convince My Clients?

You, as the designer, might see the potential of this pattern, but what if your client or your boss doesn’t? I would answer this problem with a couple of arguments:

  • Mobile apps have been placing valuable menu items to the bottom for years already. Just send them these two articles for starters:
  • I had noticed cases in which popular mobile apps started to shift important bits to the bottom. A good example is Uber. For them, the search bar is one of the most important items on the screen. In the old design, its position was at the top. Now, they’ve shifted it to the bottom. Could we be on to something here?

Old and new Uber search bar designs

The old and new Uber search bar design (Large preview)

Shifting important navigation items to the bottom is not a new thing in mobile app design. It’s just that — for some reason — the web industry has not caught up on this just yet.

Summary

The facts are quite clear: Phones are getting bigger, and some parts of the screen are easier to interact with than others. Having the hamburger menu at the top provides too big of an interaction cost, and we have a large number of amazing mobile app designs that utilize the bottom part of the screen. Maybe it’s time for the web design world to start using these ideas on websites as well?

I understand that all of this is not a foolproof solution for all use cases, but it’s worth a shot. It helps make the experience just a tad bit better. I’m interested in hearing your thoughts below!

Useful Reading Resources

Smashing Editorial
(cc, il)

Source: Smashing Magazine, Bottom Navigation Pattern On Mobile Web Pages: A Better Alternative?

Beyond The Browser: Getting Started With Serverless WebAssembly

dreamt up by webguru in Uncategorized | Comments Off on Beyond The Browser: Getting Started With Serverless WebAssembly

Beyond The Browser: Getting Started With Serverless WebAssembly

Beyond The Browser: Getting Started With Serverless WebAssembly

Robert Aboukhalil



Now that WebAssembly is supported by all major browsers and more than 85% of users worldwide, JavaScript is no longer the only browser language in town. If you haven’t heard, WebAssembly is a new low-level language that runs in the browser. It’s also a compilation target, which means you can compile existing programs written in languages such as C, C++, and Rust into WebAssembly, and run those programs in the browser. So far, WebAssembly has been used to port all sorts of applications to the web, including desktop applications, command-line tools, games and data science tools.

Note: For an in-depth case study of how WebAssembly can be used inside the browser to speed up web applications, check out my previous article.

WebAssembly Outside The Web?

Although most WebAssembly applications today are browser-centric, WebAssembly itself wasn’t originally designed just for the web, but really for any sandboxed environment. In fact, there’s recently been a lot of interest in exploring how WebAssembly could be useful outside the browser, as a general approach for running binaries on any OS or computer architecture, so long as there is a WebAssembly runtime that supports that system. In this article, we’ll look at how WebAssembly can be run outside the browser, in a serverless/Function-as-a-Service (FaaS) fashion.

WebAssembly For Serverless Applications

In a nutshell, serverless functions are a computing model where you hand your code to a cloud provider, and let them execute and manage scaling that code for you. For example, you can ask for your serverless function to be executed anytime you call an API endpoint, or to be driven by events, such as when a file is uploaded to your cloud bucket. While the term “serverless” may seem like a misnomer since servers are clearly involved somewhere along the way, it is serverless from our point of view since we don’t need to worry about how to manage, deploy or scale those servers.

Although these functions are usually written in languages like Python and JavaScript (Node.js), there are a number of reasons you might choose to use WebAssembly instead:

  1. Faster Initialization Times
    Serverless providers that support WebAssembly (including Cloudflare and Fastly report that they can launch functions at least an order of magnitude faster than most cloud providers can with other languages. They achieve this by running tens of thousands of WebAssembly modules in the same process, which is possible because the sandboxed nature of WebAssembly makes for a more efficient way of obtaining the isolation that containers are traditionally used for.
  2. No Rewrites Needed
    One of the main appeals of WebAssembly in the browser is the ability to port existing code to the web without having to rewrite everything to JavaScript. This benefit still holds true in the serverless use case because cloud providers limit which languages you can write your serverless functions in. Typically, they will support Python, Node.js, and maybe a few others, but certainly not C, C++, or Rust. By supporting WebAssembly, serverless providers can indirectly support a lot more languages.
  3. More Lightweight
    When running WebAssembly in the browser, we’re relying on the end user’s computer to perform our computations. If those computations are too intensive, our users won’t be happy when their computer fan starts whirring. Running WebAssembly outside the browser gives us the speed and portability benefits of WebAssembly, while also keeping our application lightweight. On top of that, since we’re running our WebAssembly code in a more predictable environment, we can potentially perform more intensive computations.

A Concrete Example

In my previous article here on Smashing Magazine, we discussed how we sped up a web application by replacing slow JavaScript calculations with C code compiled to WebAssembly. The web app in question was fastq.bio, a tool for previewing the quality of DNA sequencing data.

As a concrete example, let’s rewrite fastq.bio as an application that makes use of serverless WebAssembly instead of running the WebAssembly inside the browser. For this article, we’ll use Cloudflare Workers, a serverless provider that supports WebAssembly and is built on top of the V8 browser engine. Another cloud provider, Fastly, is working on a similar offering, but based on their Lucet runtime.

First, let’s write some Rust code to analyze the data quality of DNA sequencing data. For convenience, we can leverage the Rust-Bio bioinformatics library to handle parsing the input data, and the wasm-bindgen library to help us compile our Rust code to WebAssembly.

Here’s a snippet of the code that reads in DNA sequencing data and outputs a JSON with a summary of quality metrics:

// Import packages
extern crate wasm_bindgen;
use bio::seq_analysis::gc;
use bio::io::fastq;
...

// This "wasm_bindgen" tag lets us denote the functions
// we want to expose in our WebAssembly module
#[wasm_bindgen]
pub fn fastq_metrics(seq: String) -> String
{
    ...

    // Loop through lines in the file
    let reader = fastq::Reader::new(seq.as_bytes());
    for result in reader.records() {
        let record = result.unwrap();
        let sequence = record.seq();

        // Calculate simple statistics on each record
        n_reads += 1.0;
        let read_length = sequence.len();
        let read_gc = gc::gc_content(sequence);

        // We want to draw histograms of these values
        // so we store their values for later plotting
        hist_gc.push(read_gc * 100.0);
        hist_len.push(read_length);

        ...
    }

    // Return statistics as a JSON blob
    json!({
        "n": n_reads,
        "hist": {
            "gc": hist_gc,
            "len": hist_len
        },
        ...
    }).to_string()
}

We then used Cloudflare’s wrangler command-line tool to do the heavy lifting of compiling to WebAssembly and deploying to the cloud. Once done, we are given an API endpoint that takes sequencing data as input and returns a JSON with data quality metrics. We can now integrate that API into our application.

Here’s a GIF of the application in action:

GIF of our application making parallel calls to a serverless WebAssembly function, and updating plots with the data it returns.
Instead of running the analysis directly in the browser, the serverless version of our application makes several POST requests in parallel to our serverless function (see right sidebar), and updates the plots each time it returns more data. (Large preview)

The full code is available on GitHub (open-source).

Putting It All In Context

To put the serverless WebAssembly approach in context, let’s consider four main ways in which we can build data processing web applications (i.e. web apps where we perform analysis on data provided by the user):

This figure shows four ways we can structure data processing in a web app: on the server (without WebAssembly), in the browser using JavaScript, in the browser using WebAssembly, and serverless WebAssembly.

Four different architectural choices that we can take for apps that process data. (Large preview)

As shown above, the data processing can be done in several places:

  1. Server-Side
    This is the approach taken by most web applications, where API calls made in the front-end launch data processing on the back-end.
  2. Client-Side JavaScript
    In this approach, the data processing code is written in JavaScript and runs in the browser. The downside is that your performance will take a hit, and if your original code wasn’t in JavaScript, you’ll need to rewrite it from scratch!
  3. Client-Side WebAssembly
    This involves compiling data analysis code to WebAssembly and running it in the browser. If the analysis code was written in languages like C, C++ or Rust (as is often the case in my field of genomics), this obviates the need to rewrite complex algorithms in JavaScript. It also provides the potential for speeding up our application (e.g. as discussed in a previous article).
  4. Serverless WebAssembly
    This involves running the compiled WebAssembly on the cloud, using a FaaS kind of model (e.g. this article).

So why would you choose the serverless approach over the others? For one thing, compared to the first approach, it has the benefits that come with using WebAssembly, especially the ability to port existing code without having to rewrite it to JavaScript. Compared to the third approach, serverless WebAssembly also means our app is more lightweight since we don’t use the user’s resources for number crunching. In particular, if the computations are fairly involved or if the data is already in the cloud, this approach makes more sense.

On the other hand, however, the app now needs to make network connections, so the application will likely be slower. Furthermore, depending on the scale of the computation and whether it is amenable to be broken down into smaller analysis pieces, this approach might not be suitable due to limitations imposed by serverless cloud providers on runtime, CPU, and RAM utilization.

Conclusion

As we saw, it is now possible to run WebAssembly code in a serverless fashion and reap the benefits of both WebAssembly (portability and speed) and those of function-as-a-service architectures (auto-scaling and per-per-use pricing). Certain types of applications — such as data analysis and image processing, to name a few — can greatly benefit from such an approach. Though the runtime suffers because of the additional round-trips to the network, this approach does allow us to process more data at a time and not put a drain on users’ resources.

Smashing Editorial
(rb, dm, yk, il)

Source: Smashing Magazine, Beyond The Browser: Getting Started With Serverless WebAssembly

Figma Tips To Kick-Start Your Design Workflow

dreamt up by webguru in Uncategorized | Comments Off on Figma Tips To Kick-Start Your Design Workflow

Figma Tips To Kick-Start Your Design Workflow

Figma Tips To Kick-Start Your Design Workflow

Philippe Hong



I have made the switch to Figma almost two years ago and I have no regrets so far. In one of my previous blog posts on the topic, I made an in-depth review of Figma, and I’m glad I could help other designers make the switch. After two years of working with this tool, I got really familiar with it and now I’d like to share with you twenty tips that I use every day and which help me work a bit faster and be more effective.

Note About Shortcuts

Most shortcuts are written for both Windows and Mac, where the Ctrl key on Windows corresponds to the Cmd key on the Mac, and Alt is used for both Alt (Windows) and Option/Alt (Mac).

For example, Ctrl/Cmd + Alt + C is Ctrl + Alt + C on Windows and Cmd + Alt/Option + C on the Mac.

Note: This article is for designers who want to try Figma or already are exploring some of its features. To get the most from the article, some experience with Figma Design would be nice to have, but not required.

1. How To Import Multiple Images At The Same Time

We use pictures and images in our designs all the time, and it would be very useful if we could make the process of changing single and multiple images more easy and straightforward.

In Figma, you have the ability to import multiple images (using the shortcut Ctrl/Cmd + Shift + K) and then place them one by one in the layers (objects) in which you want them to appear. This is quite handy because you can see the images being imported and then placed in realtime.

import multilple images in Figma
A quick look of how to import multiple images in Figma (Large preview)

2. Better Renaming Options By Using The Layers Batch Rename Feature

Sometimes (and I really mean many times!), we need to rename a group of layers when we need to prepare our design for export (export as icons, or as a set of images), or just when we need to perform a “deep clean” process inside a design file.

In Figma, you have the ability to batch rename layers (and frames) which is a really handy feature. You can rename the entire layer name or just a portion of it. You can also find and rename a specific character in a layer name, and you can add a different number to each layer that will be later exported as a separate file. You can also do a search and replace by just typing in the “Match” field.

I find this feature extremely useful.

rename multilple layers in Figma
A quick look on how to batch rename layers in Figma (Large preview)

Note about layers: If you’re relatively new to Figma, the following Figma help page will shed some light on layers, frames, objects, groups of objects, and more.

3. Using An Emoji In The Frame Name To Display Its Current Work State

Since we started using Figma in our design team, our workflow has been more collaborative, as we usually work on the same design files, and sometimes we even work on them simultaneously.

To know which Frame or screen is still work in progress, and which one is ready (final variant completed), we add an emoji (Windows shortcut: Win key + . or Win key + ; / Mac shortcut: Cmd + Ctrl + space) before the frame name so everyone can see at a glance the frame’s current state.

current state emoji in Figma

An example of current state emoji I use in my projects (Large preview)

4. Re-Organizing Items

One of Figma’s great features is the ability to re-organize items inside a Frame. It’s very handy when used on icons, lists or tabs as shown below:

Reorganise items in Figma
A quick look on how to re-organize your items in Figma (Large preview)

Use Proper Naming To Organize Your Styles (Texts, Colors, Effects)

Local Styles is one of the best features in Figma. It allows you to create a design system or guideline for all components so you can reuse them easily. And if you change the Master Style, it changes all the components linked to it. Super powerful! However, you can get lost with all your styles if you don’t name and categorize them the right way. I’ll share with you how I structured my styles in Figma — read on!

5. Text Styles Naming

You can organize your text styles in subcategories by adding a “/”. For example, I would add a “Heading” and “/” so I’ll have all my headings inside the category “Heading.” Sounds fancy but it’s easier to navigate when you have a lot of different font sizes. Works for Texts and also Colors.

List of Text styles naming in Figma
My List of Text styles naming convention (Large preview)

List of Text styles naming in Figma

My List of Text styles naming convention (Large preview)

6. Adding A Description For Each Style As A Guide

It can be handy to know where to use different components by adding a quick description of how to use the style and where, especially when you have a team of designers. You can add a description when editing the text style, color style or any components.

Style description in Figma
How to add a description for each style (Large preview)

7. How To Switch Instance From The Sidebar

A lot of times, we end up with a lot of components, icons, etc., so the dropdown menu to switch instance is probably not the best way to do this. The little trick is that you can, from the sidebar, drag the component by holding Alt + Ctrl/Cmd to the component you want to switch. Easier and faster!

Switch instance from the sidebar in Figma
How to switch instance from the sidebar (Large preview)

8. How To Copy/Paste All Properties

When duplicating an element or when I just want to copy the style of an element, I can quickly copy the element’s properties (Ctrl/Cmd + Alt + C) and paste them (Ctrl/Cmd + V) on a new element. It’s quite handy for images and styling elements with multiple properties, e.g., fill and stroke, etc.

Copy/paste all properties feature in Figma
A quick view of the copy/paste property feature (Large preview)

9. How To Copy/Paste A Single Property

Another shortcut that I found very useful is the ability to copy a single property — and you can select which property to copy! Select the property from the right panel (like shown in the video) and with a simple Ctrl/Cmd + C and then Ctrl/Cmd + V paste it on another object. I found this to be very useful for images.

Copy/paste property feature in Figma
You can select a single property to copy like shown in this video. (Large preview)

10. Search For Elements With The Same Properties, Instance, Style, And So On

When you have a complex design file, or you just want to tidy up your design system, it’s quite handy to be able to search for elements with the same property (a specific color, for example), and then change the color to a Color Style. Super-useful after you’re settled with the design system and need to better organize all the components!

Select all with the Same Properties menu

The ‘Same Properties’ menu in Figma helps you to select all. (Large preview)

11. Use The Scale Tool To Resize Objects And Their Properties

I found it useful to be able to scale an element and its properties (stroke, effects applied to the object, etc.) all at the same time with the Scale tool (K). I found Figma a bit easier than Sketch in this regard, as you don’t have to select the size of the object. When you scale the object, both the object’s dimensions and its properties will resize proportionally. And by holding Shift, you’ll also keep the ratio while expanding or downsizing the object.

Note: If you need to change the size of an object without changing its properties (stroke, effects, etc.), use the Select tool to select the object, then resize it by using the Properties panel. If you use the Scale tool and resize the object, then both the object’s size and its properties will resize.

Resize tool in Figma
The difference between the normal resize and the scale tool (Large preview)

12. Resize A Frame Without Resizing The Layers Inside It

When designing for different screen resolutions, you want to be able to resize the screen frame without having to resize all the elements inside the frame. In order to do that, hold Ctrl/Cmd while you perform the resize operation. Magic!

Resize frame in Figma
A quick view of resizing frame without resizing the layers inside (Large preview)

13. Create Graphs/Arc In Seconds

With Figma, you can create graphs/arc in literally seconds! No more cutting paths on a circle to create a custom graph. Here’s how you create a loading arc — and all those values can be precisely controlled from the Properties panel on the right.

Graph tool in Figma
A quick look on how to create graphs in seconds (Large preview)

14. Change Spacing On The Go

I love Figma’s feature that allows you to change the spacing for a group of elements. It makes it super easy to lay out a group of elements around your screen. I use this feature for multiple elements but also for single elements as well.

Change spacing in Figma
A quick look on how to change the spacing between objects (Large preview)

15. Component Keywords For Easy Search

When you’re starting to have lots of components, it becomes difficult sometimes to find a specific component in your library. That’s when the component keywords come in handy. You can add keywords to any component so even though the component’s name is different, you’ll have the keywords which will allow to find it more easily. You’ll find an example below:

Keywords in components in Figma
Add keywords in components for easy searching (Large preview)

16. Restore An Earlier Version Of A Design File Or Share The Link To An Earlier Version

I love the feature to be able to go back to a previous version of the file I am currently working on.

No matter the reason (you made a mistake, or a client asks you to switch to an earlier version, etc.), it is really handy to be able to go back in time to a previous version. And not only that, but Figma also lets you copy the link to the previous version so you don’t have to delete the most recent version of the file. Smart!

History version in Figma
Going back in time in your history version (Large preview)

17. UI Kit Libraries To Kick-Start Your Projects

I often use the UI kit libraries to kick-start my projects. For example, I use the Wireframy Kit whenever I need to design some wireframes. I just need to activate the library, and I’m ready to go! I also often use Bootstrap Grid and Figma Redlines. (There’s a ton of free assets available — check them out and pick the ones you need.)

UI Kits in Figma
One of the UI Kit “Wireframy” which I use. (Large preview)

18. Use GIFs In Prototypes

Figma just added the ability to add GIF files to your prototypes, thus adding the possibility to add user interaction animations within your prototypes. Here’s a preview of it from Aris Acoba:

https://platform.twitter.com/widgets.js

19. Figma, Tidy Up!

Figma’s Tidy Up feature is really when you want to quickly rearrange elements in a grid or just to make everything aligned. Together with the features which I mentioned in point 4 and point 14 — it’s super powerful! Also, another way to tidy up is by hovering over the bottom-right corner of a selection and clicking the blue icon.

Tidy up in Figma
A quick look on the ‘Tidy Up’ feature in Figma (Large preview)

20. View Settings

It took me a bit of time to find those settings but they are quite handy when you know where they are located. You can configure how you see your workplace in the “Settings” dropdown menu in the top right corner of the window. Allowing you to show Rulers, the Grid, enable/disable “Snap to Pixel Grid” (which sometimes is a bit annoying), but also hide the other players’ (designers) cursors when you want a bit of focus and don’t want to be distracted by others.

View settings panel in Figma

The ‘View’ settings panel in Figma (Large preview)

21. Bonus Tip: Figma Plugins

Figma just recently introduced their new plugins feature which will allow people to build custom plugins tailored for their own workflows.

I think plugins will add a lot of value to the entire Figma ecosystem and will enhance our design workflows. Some of the best plugins I have tried so far include:

  • Content Reel
  • Unsplash
  • Stark
  • Image Palette
  • Google Sheet sync

Plugins in Figma

A list of Plugins in Figma (Large preview)

Have a try yourself and maybe you could even build your own plugin to suit your needs!

Further Reading on SmashingMag:

Smashing Editorial
(mb, yk, il)

Source: Smashing Magazine, Figma Tips To Kick-Start Your Design Workflow

Collective #543

dreamt up by webguru in Uncategorized | Comments Off on Collective #543







C543_reactlayout

React Layouts

Grab-and-go layouts for React including code examples for Rebass, Theme UI, or Emotion. By Brent Jackson.

Check it out


C543_ruffle

Ruffle

Ruffle is an Adobe Flash Player emulator written in the Rust programming language. Ruffle targets both the desktop and the web using WebAssembly.

Check it out














C543_svelte

Svelte tutorial

A tutorial that will teach you everything you need to know to build fast, small web applications easily with Svelte.

Check it out


C543_null

Introducing nushell

The introduction of a new shell, written in Rust that draws inspiration from the classic Unix philosophy of pipelines and the structured data approach of PowerShell.

Read it


Collective #543 was written by Pedro Botelho and published on Codrops.


Source: Codrops, Collective #543

Creating A Shopping Cart With HTML5 Web Storage

dreamt up by webguru in Uncategorized | Comments Off on Creating A Shopping Cart With HTML5 Web Storage

Creating A Shopping Cart With HTML5 Web Storage

Creating A Shopping Cart With HTML5 Web Storage

Matt Zand



With the advent of HTML5, many sites were able to replace JavaScript plugin and codes with simple more efficient HTML codes such as audio, video, geolocation, etc. HTML5 tags made the job of developers much easier while enhancing page load time and site performance. In particular, HTML5 web storage was a game changer as they allow users’ browsers to store user data without using a server. So the creation of web storage, allowed front-end developers to accomplish more on their website without knowing or using server-side coding or database.

Online e-commerce websites predominantly use server-side languages such as PHP to store users’ data and pass them from one page to another. Using JavaScript back-end frameworks such as Node.js, we can achieve the same goal. However, in this tutorial, we’ll show you step by step how to build a shopping cart with HTML5 and some minor JavaScript code. Other uses of the techniques in this tutorial would be to store user preferences, the user’s favorite content, wish lists, and user settings like name and password on websites and native mobile apps without using a database.

Many high-traffic websites rely on complex techniques such as server clustering, DNS load balancers, client-side and server-side caching, distributed databases, and microservices to optimize performance and availability. Indeed, the major challenge for dynamic websites is to fetch data from a database and use a server-side language such as PHP to process them. However, remote database storage should be used only for essential website content, such as articles and user credentials. Features such as user preferences can be stored in the user’s browser, similar to cookies. Likewise, when you build a native mobile app, you can use HTML5 web storage in conjunction with a local database to increase the speed of your app. Thus, as front-end developers, we need to explore ways in which we can exploit the power of HTML5 web storage in our applications in the early stages of development.

I have been a part of a team developing a large-scale social website, and we used HTML5 web storage heavily. For instance, when a user logs in, we store the hashed user ID in an HTML5 session and use it to authenticate the user on protected pages. We also use this feature to store all new push notifications — such as new chat messages, website messages, and new feeds — and pass them from one page to another. When a social website gets high traffic, total reliance on the server for load balancing might not work, so you have to identify tasks and data that can be handled by the user’s browser instead of your servers.

Project Background

A shopping cart allows a website’s visitor to view product pages and add items to their basket. The visitor can review all of their items and update their basket (such as to add or remove items). To achieve this, the website needs to store the visitor’s data and pass them from one page to another, until the visitor goes to the checkout page and makes a purchase. Storing data can be done via a server-side language or a client-side one. With a server-side language, the server bears the weight of the data storage, whereas with a client-side language, the visitor’s computer (desktop, tablet or smartphone) stores and processes the data. Each approach has its pros and cons. In this tutorial, we’ll focus on a simple client-side approach, based on HTML5 and JavaScript.

Note: In order to be able to follow this tutorial, basic knowledge of HTML5, CSS and JavaScript is required.

Project Files

Click here to download the project’s source files. You can see a live demo, too.

Overview Of HTML5 Web Storage

HTML5 web storage allows web applications to store values locally in the browser that can survive the browser session, just like cookies. Unlike cookies that need to be sent with every HTTP request, web storage data is never transferred to the server; thus, web storage outperforms cookies in web performance. Furthermore, cookies allow you to store only 4 KB of data per domain, whereas web storage allows at least 5 MB per domain. Web storage works like a simple array, mapping keys to values, and they have two types:

  • Session storage
    This stores data in one browser session, where it becomes available until the browser or browser tab is closed. Popup windows opened from the same window can see session storage, and so can iframes inside the same window. However, multiple windows from the same origin (URL) cannot see each other’s session storage.
  • Local storage
    This stores data in the web browser with no expiration date. The data is available to all windows with the same origin (domain), even when the browser or browser tabs are reopened or closed.

Both storage types are currently supported in all major web browsers. Keep in mind that you cannot pass storage data from one browser to another, even if both browsers are visiting the same domain.

Build A Basic Shopping Cart

To build our shopping cart, we first create an HTML page with a simple cart to show items, and a simple form to add or edit the basket. Then, we add HTML web storage to it, followed by JavaScript coding. Although we are using HTML5 local storage tags, all steps are identical to those of HTML5 session storage and can be applied to HTML5 session storage tags. Lastly, we’ll go over some jQuery code, as an alternative to JavaScript code, for those interested in using jQuery.

Add HTML5 Local Storage To Shopping Cart

Our HTML page is a basic page, with tags for external JavaScript and CSS referenced in the head.

<!DOCTYPE HTML>
<html lang="en-US">
<head>
<title>HTML5 Local Storage Project</title>
<META charset="UTF-8">
<META name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<META NAME='rating' CONTENT='General' />
<META NAME='expires' CONTENT='never' />
<META NAME='language' CONTENT='English, EN' />
<META name="description" content="shopping cart project with HTML5 and JavaScript">
<META name="keywords" content="HTML5,CSS,JavaScript, html5 session storage, html5 local storage">
<META name="author" content="dcwebmakers.com">
http://Storage.js
<link rel="stylesheet" href="StorageStyle.css">
</head>

Below is the HTML content for the page’s body:

<form name=ShoppingList>

        
Item: Quantity:

Shopping List

</form>

Adding JavaScript To The Shopping Cart

We’ll create and call the JavaScript function doShowAll() in the onload() event to check for browser support and to dynamically create the table that shows the storage name-value pair.

<body onload="doShowAll()">

Alternatively, you can use the JavaScript onload event by adding this to the JavaScript code:

window.load=doShowAll();

Or use this for jQuery:

$( window ).load(function() {
  doShowAll();
});

In the CheckBrowser() function, we would like to check whether the browser supports HTML5 storage. Note that this step might not be required because most modern web browsers support it.

/*
=====> Checking browser support.
 //This step might not be required because most modern browsers do support HTML5.
 */
 //Function below might be redundant.
function CheckBrowser() {
    if ('localStorage' in window && window['localStorage'] !== null) {
        // We can use localStorage object to store data.
        return true;
    } else {
            return false;
    }
}

Inside the doShowAll(), if the CheckBrowser() function evaluates first for browser support, then it will dynamically create the table for the shopping list during page load. You can iterate the keys (property names) of the key-value pairs stored in local storage inside a JavaScript loop, as shown below. Based on the storage value, this method populates the table dynamically to show the key-value pair stored in local storage.

// Dynamically populate the table with shopping list items.
//Step below can be done via PHP and AJAX, too. 
function doShowAll() {
    if (CheckBrowser()) {
        var key = "";
        var list = "<tr><th>Item</th><th>Value</th></tr>n";
        var i = 0;
        //For a more advanced feature, you can set a cap on max items in the cart.
        for (i = 0; i <= localStorage.length-1; i++) {
            key = localStorage.key(i);
            list += "<tr><td>" + key + "</td>n<td>"
                    + localStorage.getItem(key) + "</td></tr>n";
        }
        //If no item exists in the cart.
        if (list == "<tr><th>Item</th><th>Value</th></tr>n") {
            list += "<tr><td><i>empty</i></td>n<td><i>empty</i></td></tr>n";
        }
        //Bind the data to HTML table.
        //You can use jQuery, too.
        document.getElementById('list').innerHTML = list;
    } else {
        alert('Cannot save shopping list as your browser does not support HTML 5');
    }
}

Note: Either you or your framework will have a preferred method of creating new DOM nodes. To keep things clear and focused, our example uses .innerHTML even though we’d normally avoid that in production code.

Tip: If you’d like to use jQuery to bind data, you can just replace document.getElementById('list').innerHTML = list; with $(‘#list’).html()=list;.

Run And Test The Shopping Cart

In the previous two sections, we added code to the HTML head, and we added HTML to the shopping cart form and basket. We also created a JavaScript function to check for browser support and to populate the basket with the items in the cart. In populating the basket items, the JavaScript fetches values from HTML web storage, instead of a database. In this part, we’ll show you how the data are inserted into the HTML5 storage engine. That is, we’ll use HTML5 local storage in conjunction with JavaScript to insert new items to the shopping cart, as well as edit an existing item in the cart.

Note: I’ve added tips sections below to show jQuery code, as an alternative to the JavaScript ones.

We’ll create a separate HTML div element to capture user input and submission. We’ll attach the corresponding JavaScript function in the onClick event for the buttons.

<input type="button" value="Save"   onclick="SaveItem()">
<input type="button" value="Update" onclick="ModifyItem()"> 
<input type="button" value="Delete" onclick="RemoveItem()">

You can set properties on the localStorage object similar to a normal JavaScript object. Here is an example of how we can set the local storage property myProperty to the value myValue:

localStorage.myProperty="myValue";

You can delete local storage property like this:

delete localStorage.myProperty;

Alternately, you can use the following methods to access local storage:

localStorage.setItem('propertyName','value'); 
localStorage.getItem('propertyName'); 
localStorage.removeItem('propertyName');

To save the key-value pair, get the value of the corresponding JavaScript object and call the setItem method:

function SaveItem() {
         
    var name = document.forms.ShoppingList.name.value;
    var data = document.forms.ShoppingList.data.value;
    localStorage.setItem(name, data);
    doShowAll();
    
}

Below is the jQuery alternative for the SaveItem function. First, add an ID to the form inputs:

<td><b>Item:</b><input type=text name="name" id="name"></td>
<td><b>Quantity:</b><input type=text name="data" id="data"></td>

Then, select the form inputs by ID, and get their values. As you can see below, it is much simpler than JavaScript:

function SaveItem() {         
    var name = $("#name").val();
    var data = $("#data").val();
    localStorage.setItem(name, data);
    doShowAll();    
}

To update an item in the shopping cart, you have to first check whether that item’s key already exists in local storage, and then update its value, as shown below:

//Change an existing key-value in HTML5 storage.
function ModifyItem() {
    var name1 = document.forms.ShoppingList.name.value;
    var data1 = document.forms.ShoppingList.data.value;
    //check if name1 is already exists
    
//Check if key exists.
            if (localStorage.getItem(name1) !=null)
            {
              //update
              localStorage.setItem(name1,data1);
              document.forms.ShoppingList.data.value = localStorage.getItem(name1);
            }
        
    
    doShowAll();
}

Below shows the jQuery alternative.

function ModifyItem() {
    var name1 = $("#name").val();
    var data1 = $("#data").val();
    //Check if name already exists.
//Check if key exists.
         if (localStorage.getItem(name1) !=null)
         {
           //update
           localStorage.setItem(name1,data1);
           var new_info=localStorage.getItem(name1);
           $("#data").val(new_info);
         }       
    
    doShowAll();
}

We will use the removeItem method to delete an item from storage.

function RemoveItem() 
{ 
var name=document.forms.ShoppingList.name.value;
document.forms.ShoppingList.data.value=localStorage.removeItem(name); 
doShowAll();
}

Tip: Similar to the previous two functions, you can use jQuery selectors in the RemoveItem function.

There is another method for local storage that allows you to clear the entire local storage. We call the ClearAll() function in the onClick event of the “Clear” button:

<input type="button" value="Clear" onclick="ClearAll()">

We use the clear method to clear the local storage, as shown below:

function ClearAll() {
    localStorage.clear();
    doShowAll();
}

Session Storage

The sessionStorage object works in the same way as localStorage. You can replace the above example with the sessionStorage object to expire the data after one session. Once the user closes the browser window, the storage will be cleared. In short, the APIs for localStorage and sessionStorage are identical, allowing you to use the following methods:

  • setItem(key, value)
  • getItem(key)
  • removeItem(key)
  • clear()
  • key(index)
  • length

Shopping Carts With Arrays And Objects

Because HTML5 web storage only supports single name-value storage, you have to use JSON or another method to convert your arrays or objects into a single string. You might need an array or object if you have a category and subcategories of items, or if you have a shopping cart with multiple data, like customer info, item info, etc. You just need to implode your array or object items into a string to store them in web storage, and then explode (or split) them back to an array to show them on another page. Let’s go through a basic example of a shopping cart that has three sets of info: customer info, item info and custom mailing address. First, we use JSON.stringify to convert the object into a string. Then, we use JSON.parse to reverse it back.

Hint: Keep in mind that the key-name should be unique for each domain.

//Customer info
//You can use array in addition to object.
var obj1 = { firstname: "John", lastname: "thomson" };
var cust = JSON.stringify(obj1);

//Mailing info
var obj2 = { state: "VA", city: "Arlington" };
var mail = JSON.stringify(obj2);

//Item info
var obj3 = { item: "milk", quantity: 2 };
var basket = JSON.stringify(obj3);

//Next, push three strings into key-value of HTML5 storage.

//Use JSON parse function below to convert string back into object or array.
var New_cust=JSON.parse(cust);

Summary

In this tutorial, we have learned how to build a shopping cart step by step using HTML5 web storage and JavaScript. We’ve seen how to use jQuery as an alternative to JavaScript. We’ve also discussed JSON functions like stringify and parse to handle arrays and objects in a shopping cart. You can build on this tutorial by adding more features, like adding product categories and subcategories while storing data in a JavaScript multi-dimensional array. Moreover, you can replace the whole JavaScript code with jQuery.

We’ve seen what other things developers can accomplish with HTML5 web storage and what other features they can add to their websites. For example, you can use this tutorial to store user preferences, favorited content, wish lists, and user settings like names and passwords on websites and native mobile apps, without using a database.

To conclude, here are a few issues to consider when implementing HTML5 web storage:

  • Some users might have privacy settings that prevent the browser from storing data.
  • Some users might use their browser in incognito mode.
  • Be aware of a few security issues, like DNS spoofing attacks, cross-directory attacks, and sensitive data compromise.
Smashing Editorial
(dm, il)

Source: Smashing Magazine, Creating A Shopping Cart With HTML5 Web Storage

Faster Image Loading With Embedded Image Previews

dreamt up by webguru in Uncategorized | Comments Off on Faster Image Loading With Embedded Image Previews

Faster Image Loading With Embedded Image Previews

Faster Image Loading With Embedded Image Previews

Christoph Erdmann



Low Quality Image Preview (LQIP) and the SVG-based variant SQIP are the two predominant techniques for lazy image loading. What both have in common is that you first generate a low-quality preview image. This will be displayed blurred and later replaced by the original image. What if you could present a preview image to the website visitor without having to load additional data?

JPEG files, for which lazy loading is mostly used, have the possibility, according to the specification, to store the data contained in them in such a way that first the coarse and then the detailed image contents are displayed. Instead of having the image built up from top to bottom during loading (baseline mode), a blurred image can be displayed very quickly, which gradually becomes sharper and sharper (progressive mode).

Representation of the temporal structure of a JPEG in baseline mode

Baseline mode (Large preview)

Representation of the temporal structure of a JPEG in progressive mode

Progressive mode (Large preview)

In addition to the better user experience provided by the appearance that is displayed more quickly, progressive JPEGs are usually also smaller than their baseline-encoded counterparts. For files larger than 10 kB, there is a 94 percent probability of a smaller image when using progressive mode according to Stoyan Stefanov of the Yahoo development team.

If your website consists of many JPEGs, you will notice that even progressive JPEGs load one after the other. This is because modern browsers only allow six simultaneous connections to a domain. Progressive JPEGs alone are therefore not the solution to give the user the fastest possible impression of the page. In the worst case, the browser will load an image completely before it starts loading the next one.

The idea presented here is now to load only so many bytes of a progressive JPEG from the server that you can quickly get an impression of the image content. Later, at a time defined by us (e.g. when all preview images in the current viewport have been loaded), the rest of the image should be loaded without requesting the part already requested for the preview again.

Shows the way the EIP (Embedded image preview) technique loads the image data in two requests.

Loading a progressive JPEG with two requests (Large preview)

Unfortunately, you can’t tell an img tag in an attribute how much of the image should be loaded at what time. With Ajax, however, this is possible, provided that the server delivering the image supports HTTP Range Requests.

Using HTTP range requests, a client can inform the server in an HTTP request header which bytes of the requested file are to be contained in the HTTP response. This feature, supported by each of the larger servers (Apache, IIS, nginx), is mainly used for video playback. If a user jumps to the end of a video, it would not be very efficient to load the complete video before the user can finally see the desired part. Therefore, only the video data around the time requested by the user is requested by the server, so that the user can watch the video as fast as possible.

We now face the following three challenges:

  1. Creating The Progressive JPEG
  2. Determine Byte Offset Up To Which The First HTTP Range Request Must Load The Preview Image
  3. Creating the Frontend JavaScript Code

1. Creating The Progressive JPEG

A progressive JPEG consists of several so-called scan segments, each of which contains a part of the final image. The first scan shows the image only very roughly, while the ones that follow later in the file add more and more detailed information to the already loaded data and finally form the final appearance.

How exactly the individual scans look is determined by the program that generates the JPEGs. In command-line programs like cjpeg from the mozjpeg project, you can even define which data these scans contain. However, this requires more in-depth knowledge, which would go beyond the scope of this article. For this, I would like to refer to my article “Finally Understanding JPG“, which teaches the basics of JPEG compression. The exact parameters that have to be passed to the program in a scan script are explained in the wizard.txt of the mozjpeg project. In my opinion, the parameters of the scan script (seven scans) used by mozjpeg by default are a good compromise between fast progressive structure and file size and can, therefore, be adopted.

To transform our initial JPEG into a progressive JPEG, we use jpegtran from the mozjpeg project. This is a tool to make lossless changes to an existing JPEG. Pre-compiled builds for Windows and Linux are available here: https://mozjpeg.codelove.de/binaries.html. If you prefer to play it safe for security reasons, it’s better to build them yourself.

From the command line we now create our progressive JPEG:

$ jpegtran input.jpg > progressive.jpg

The fact that we want to build a progressive JPEG is assumed by jpegtran and does not need to be explicitly specified. The image data will not be changed in any way. Only the arrangement of the image data within the file is changed.

Metadata irrelevant to the appearance of the image (such as Exif, IPTC or XMP data), should ideally be removed from the JPEG since the corresponding segments can only be read by metadata decoders if they precede the image content. Since we cannot move them behind the image data in the file for this reason, they would already be delivered with the preview image and enlarge the first request accordingly. With the command-line program exiftool you can easily remove these metadata:

$ exiftool -all= progressive.jpg

If you don’t want to use a command-line tool, you can also use the online compression service compress-or-die.com to generate a progressive JPEG without metadata.

2. Determine Byte Offset Up To Which The First HTTP Range Request Must Load The Preview Image

A JPEG file is divided into different segments, each containing different components (image data, metadata such as IPTC, Exif and XMP, embedded color profiles, quantization tables, etc.). Each of these segments begins with a marker introduced by a hexadecimal FF byte. This is followed by a byte indicating the type of segment. For example, D8 completes the marker to the SOI marker FF D8 (Start Of Image), with which each JPEG file begins.

Each start of a scan is marked by the SOS marker (Start Of Scan, hexadecimal FF DA). Since the data behind the SOS marker is entropy coded (JPEGs use the Huffman coding), there is another segment with the Huffman tables (DHT, hexadecimal FF C4) required for decoding before the SOS segment. The area of interest for us within a progressive JPEG file, therefore, consists of alternating Huffman tables/scan data segments. Thus, if we want to display the first very rough scan of an image, we have to request all bytes up to the second occurrence of a DHT segment (hexadecimal FF C4) from the server.

Shows the SOS markers in a JPEG file

Structure of a JPEG file (Large preview)

In PHP, we can use the following code to read the number of bytes required for all scans into an array:

<?php
$img = "progressive.jpg";
$jpgdata = file_get_contents($img);
$positions = [];
$offset = 0;
while ($pos = strpos($jpgdata, "xFFxC4", $offset)) {
    $positions[] = $pos+2;
    $offset = $pos+2;
}

We have to add the value of two to the found position because the browser only renders the last row of the preview image when it encounters a new marker (which consists of two bytes as just mentioned).

Since we are interested in the first preview image in this example, we find the correct position in $positions[1] up to which we have to request the file via HTTP Range Request. To request an image with a better resolution, we could use a later position in the array, e.g. $positions[3].

3. Creating The Frontend JavaScript Code

First of all, we define an img tag, to which we give the just evaluated byte position:

<img data-src="progressive.jpg" data-bytes="<?= $positions[1] ?>">

As is often the case with lazy load libraries, we do not define the src attribute directly so that the browser does not immediately start requesting the image from the server when parsing the HTML code.

With the following JavaScript code we now load the preview image:

var $img = document.querySelector("img[data-src]");
var URL = window.URL || window.webkitURL;

var xhr = new XMLHttpRequest();
xhr.onload = function(){
    if (this.status === 206){
        $img.src_part = this.response;
        $img.src = URL.createObjectURL(this.response);
    }
}

xhr.open('GET', $img.getAttribute('data-src'));
xhr.setRequestHeader("Range", "bytes=0-" + $img.getAttribute('data-bytes'));
xhr.responseType = 'blob';
xhr.send();

This code creates an Ajax request that tells the server in an HTTP range header to return the file from the beginning to the position specified in data-bytes… and no more. If the server understands HTTP Range Requests, it returns the binary image data in an HTTP-206 response (HTTP 206 = Partial Content) in the form of a blob, from which we can generate a browser-internal URL using createObjectURL. We use this URL as src for our img tag. Thus we have loaded our preview image.

We store the blob additionally at the DOM object in the property src_part, because we will need this data immediately.

In the network tab of the developer console you can check that we have not loaded the complete image, but only a small part. In addition, the loading of the blob URL should be displayed with a size of 0 bytes.

Shows the network console and the sizes of the HTTP requests

Network console when loading the preview image (Large preview)

Since we already load the JPEG header of the original file, the preview image has the correct size. Thus, depending on the application, we can omit the height and width of the img tag.

Alternative: Loading the preview image inline

For performance reasons, it is also possible to transfer the data of the preview image as data URI directly in the HTML source code. This saves us the overhead of transferring the HTTP headers, but the base64 encoding makes the image data one third larger. This is relativized if you deliver the HTML code with a content encoding like gzip or brotli, but you should still use data URIs for small preview images.

Much more important is the fact that the preview images are available immediately and there is no noticeable delay for the user when building the page.

First of all, we have to create the data URI, which we then use in the img tag as src. For this, we create the data URI via PHP, whereby this code is based on the code just created, which determines the byte offsets of the SOS markers:

<?php
…

$fp = fopen($img, 'r');
$data_uri = 'data:image/jpeg;base64,'. base64_encode(fread($fp, $positions[1]));
fclose($fp);

The created data URI is now directly inserted into the `img` tag as src:

<img src="<?= $data_uri ?>" data-src="progressive.jpg" alt="">

Of course, the JavaScript code must also be adapted:


var $img = document.querySelector("img[data-src]");

var binary = atob($img.src.slice(23));
var n = binary.length;
var view = new Uint8Array(n);
while(n--) { view[n] = binary.charCodeAt(n); }

$img.src_part = new Blob([view], { type: 'image/jpeg' });
$img.setAttribute('data-bytes', $img.src_part.size - 1);

Instead of requesting the data via Ajax request, where we would immediately receive a blob, in this case we have to create the blob ourselves from the data URI. To do this, we free the data-URI from the part that does not contain image data: data:image/jpeg;base64. We decode the remaining base64 coded data with the atob command. In order to create a blob from the now binary string data, we have to transfer the data into a Uint8 array, which ensures that the data is not treated as a UTF-8 encoded text. From this array, we can now create a binary blob with the image data of the preview image.

So that we don’t have to adapt the following code for this inline version, we add the attribute data-bytes on the img tag, which in the previous example contains the byte offset from which the second part of the image has to be loaded.

In the network tab of the developer console, you can also check here that loading the preview image does not generate an additional request, while the file size of the HTML page has increased.

Shows the network console and the sizes of the HTTP requests

Network console when loading the preview image as data URI (Large preview)

Loading the final image

In a second step we load the rest of the image file after two seconds as an example:

setTimeout(function(){
    var xhr = new XMLHttpRequest();
    xhr.onload = function(){
        if (this.status === 206){
            var blob = new Blob([$img.src_part, this.response], { type: 'image/jpeg'} );
            $img.src = URL.createObjectURL(blob);
        }
    }
    xhr.open('GET', $img.getAttribute('data-src'));
    xhr.setRequestHeader("Range", "bytes="+ (parseInt($img.getAttribute('data-bytes'), 10)+1) +'-');
    xhr.responseType = 'blob';
    xhr.send();
}, 2000);

In the Range header this time we specify that we want to request the image from the end position of the preview image to the end of the file. The answer to the first request is stored in the property src_part of the DOM object. We use the responses from both requests to create a new blob per new Blob(), which contains the data of the whole image. The blob URL generated from this is used again as src of the DOM object. Now the image is completely loaded.

Also now we can check the loaded sizes in the network tab of the developer console again..

Shows the network console and the sizes of the HTTP requests

Network console when loading the entire image (31.7 kB) (Large preview)

Prototype

At the following URL I have provided a prototype where you can experiment with different parameters: http://embedded-image-preview.cerdmann.com/prototype/

The GitHub repository for the prototype can be found here: https://github.com/McSodbrenner/embedded-image-preview

Considerations At The End

Using the Embedded Image Preview (EIP) technology presented here, we can load qualitatively different preview images from progressive JPEGs with the help of Ajax and HTTP Range Requests. The data from these preview images is not discarded but instead reused to display the entire image.

Furthermore, no preview images need to be created. On the server-side, only the byte offset at which the preview image ends has to be determined and saved. In a CMS system, it should be possible to save this number as an attribute on an image and take it into account when outputting it in the img tag. Even a workflow would be conceivable, which supplements the file name of the picture by the offset, e.g. progressive-8343.jpg, in order not to have to save the offset apart from the picture file. This offset could be extracted by the JavaScript code.

Since the preview image data is reused, this technique could be a better alternative to the usual approach of loading a preview image and then a WebP (and providing a JPEG fallback for non-WebP-supporting browsers). The preview image often destroys the storage advantages of the WebP, which does not support progressive mode.

Currently, preview images in normal LQIP are of inferior quality, since it is assumed that loading the preview data requires additional bandwidth. As Robin Osborne already made clear in a blog post in 2018, it doesn’t make much sense to show placeholders that don’t give you an idea of the final image. By using the technique suggested here, we can show some more of the final image as a preview image without hesitation by presenting the user a later scan of the progressive JPEG.

In case of a weak network connection of the user, it might make sense, depending on the application, not to load the whole JPEG, but e.g. to omit the last two scans. This produces a much smaller JPEG with an only slightly reduced quality. The user will thank us for it, and we don’t have to store an additional file on the server.

Now I wish you a lot of fun trying out the prototype and look forward to your comments.

Smashing Editorial
(dm, yk, il)

Source: Smashing Magazine, Faster Image Loading With Embedded Image Previews

Collective #542

dreamt up by webguru in Uncategorized | Comments Off on Collective #542






C542_Aristide

The updated portfolio by Aristide Benoist is a true WebGL powered gem.

Check it out


C542_nuxtpress

NuxtPress

NuxtPress is a microframework that will automatically register routes, templates and configuration options in your Nuxt application. It also takes care of loading Markdown files and making pre-rendered static files automatically available.

Check it out







C542_auth

useAuth

UseAuth offers a simple way to add authentication to your React app. It handles users, login forms and redirects.

Check it out



C542_clamp

line-clamp

This CSS-Tricks Almanac entry by Geoff Graham is about line-clamp, a very practical property that truncates text at a specific number of lines.

Read it


C542_gopablo

GoPablo

GoPablo is a static site generator with a modern development workflow, integrated web server, auto-reload, CSS preprocessors, and ES6 ready.

Check it out








Collective #542 was written by Pedro Botelho and published on Codrops.


Source: Codrops, Collective #542

Testing Made Easier Via Framework Minimalism And Software Architecture

dreamt up by webguru in Uncategorized | Comments Off on Testing Made Easier Via Framework Minimalism And Software Architecture

Testing Made Easier Via Framework Minimalism And Software Architecture

Testing Made Easier Via Framework Minimalism And Software Architecture

Ryan Kay



Like many other Android developers, my initial foray into testing on the platform lead me to be immediately confronted with a demoralizing degree of jargon. Further, what few examples I came across at the time (circa 2015) did not present practical use cases which may have inclined me to think that the cost to benefit ratio of learning a tool like Espresso in order to verify that a TextView.setText(…) was working properly, was a reasonable investment.

To make matters even worse, I did not have a working understanding of software architecture in theory or practice, which meant that even if I bothered to learn these frameworks, I would have been writing tests for monolithic applications comprised of a few god classes, written in spaghetti code. The punchline is that building, testing, and maintaining such applications is an exercise in self-sabotage quite regardless of your framework expertise; yet this realization only becomes clear after one has built a modular, loosely-coupled, and highly-cohesive application.

From here we arrive at one of the main points of discussion in this article, which I will summarize in plain language here: Among the primary benefits of applying the golden principles of software architecture (do not worry, I will discuss them with simple examples and language), is that your code can become easier to test. There are other benefits to applying such principles, but the relationship between software architecture and testing is the focus of this article.

However, for the sake of those who wish to understand why and how we test our code, we will first explore the concept of testing by analogy; without requiring you to memorize any jargon. Before getting deeper into the primary topic, we will also look at the question of why so many testing frameworks exist, for in examining this we may begin to see their benefits, limitations, and perhaps even an alternative solution.

Testing: Why And How

This section will not be new information for any seasoned tester, but perhaps you may enjoy this analogy nonetheless. Of course I am a software engineer, not a rocket engineer, but for a moment I will borrow an analogy which relates to designing and building objects both in physical space, and in the memory space of a computer. It turns out that while the medium changes, the process is in principle quite the same.

Suppose for a moment that we are rocket engineers, and our job is to build the first stage* rocket booster of a space shuttle. Suppose as well, that we have come up with a serviceable design for the first stage to begin building and testing in various conditions.

“First stage” refers to boosters which are fired when the rocket is first launched

Before we get to the process, I would like to point out why I prefer this analogy: You should not have any difficulty answering the question of why we are bothering to test our design before putting it in situations where human lives are at stake. While I will not try to convince you that testing your applications before launch could save lives (although it is possible depending on the nature of the application), it could save ratings, reviews, and your job. In the broadest sense, testing is the way in which we make sure that single parts, several components, and whole systems work before we employ them in situations where it is critically important for them to not fail.

Returning to the how aspect of this analogy, I will introduce the process by which engineers go about testing a particular design: redundancy. Redundancy is simple in principle: Build copies of the component to be tested to the same design specification as what you wish to use at launch time. Test these copies in an isolated environment which strictly controls for preconditions and variables. While this does not guarantee that the rocket booster will work properly when integrated in the whole shuttle, one can be certain that if it does not work in a controlled environment, it will be very unlikely to work at all.

Suppose that of the hundreds, or perhaps thousands of variables which the copies of the rocket design have been tested against, it comes down to ambient temperatures in which the rocket booster will be test fired. Upon testing at 35° Celsius, we see that everything functions without error. Again, the rocket is tested at roughly room temperature without failure. The final test will be at the lowest recorded temperature for the launch site, at -5° Celcius. During this final test, the rocket fires, but after a short period, the rocket flares up and shortly thereafter explodes violently; but fortunately in a controlled and safe environment.

At this point, we know that changes in temperature appear to be at least involved in the failed test, which leads us to consider what parts of the rocket booster may be adversely effected by cold temperatures. Over time, it is discovered that one key component, a rubber O-ring which serves to staunch the flow of fuel from one compartment to another, becomes rigid and ineffectual when exposed to temperatures approaching or below freezing.

It is possible that you have noticed that his analogy is loosely based on the tragic events of the Challenger space shuttle disaster. For those unfamiliar, the sad truth (insofar as investigations concluded) is that there were plenty of failed tests and warnings from the engineers, and yet administrative and political concerns spurred the launch to proceed regardless. In any case, whether or not you have memorized the term redundancy, my hope is that you have grasped the fundamental process for testing parts of any kind of system.

Concerning Software

Whereas the prior analogy explained the fundamental process for testing rockets (while taking plenty of liberty with the finer details), I will now summarize in a manner which is likely more relevant to you and I. While it is possible to test software by only launching it to devices once it is in any sort of deployable state, I suppose instead that we can apply the principle of redundancy to the individual parts of the application first.

This means that we create copies of the smaller parts of the whole application (commonly referred to as Units of software), set up an isolated test environment, and see how they behave based on whatever variables, arguments, events, and responses which may occur at runtime. Testing is truly as simple as that in theory, but the key to even getting to this process lies in building applications which are feasibly testable. This comes down to two concerns which we will look at in the next two sections. The first concern has to do with the test environment, and the second concern has to do with the way in which we structure applications.

Why Do We Need Frameworks?

In order to test a piece of software (henceforth referred to as a Unit, although this definition is deliberately an over-simplification), it is necessary to have some kind of testing environment which allows you to interact with your software at runtime. For those building applications to be executed purely on a JVM (Java Virtual Machine) environment, all that is required to write tests is a JRE (Java Runtime Environment). Take for example this very simple Calculator class:

class Calculator {
    private int add(int a, int b){
        return a + b;
    }

    private int subtract(int a, int b){
        return a - b;
    }
}

In absence of any frameworks, as long as we have a test class which contains a mainfunction to actually execute our code, we can test it. As you may recall, the main function denotes the starting point of execution for a simple Java program. As for what we are testing for, we simply feed some test data into the Calculator’s functions and verify that it is performing basic arithmetic properly:

public class Main {

    public static void main(String[] args){
    //create a copy of the Unit to be tested
        Calculator calc = new Calculator();
    //create test conditions to verify behaviour
        int addTest = calc.add(2, 2);
        int subtractTest = calc.subtract(2, 2);

    //verify behaviour by assertion
        if (addTest == 4) System.out.println("addTest has passed.");
        else System.out.println("addTest has failed.");

        if (subtractTest == 0) System.out.println("subtractTest has passed.");
        else System.out.println("subtractTest has failed.");
    }
}

Testing an Android application is of course, a completely different procedure. Although there is a main function buried deep within the source of the ZygoteInit.java file (the finer details of which are not important here), which is invoked prior to an Android application being launched on the JVM, even a junior Android developer ought to know that the system itself is responsible for calling this function; not the developer. Instead, the entry points for Android applications happen to be the Application class, and any Activity classes which the system can be pointed to via the AndroidManifest.xml file.

All of this is just a lead up to the fact that testing Units in an Android application presents a greater level of complexity, strictly because our testing environment must now account for the Android platform.

Taming The Problem Of Tight Coupling

Tight coupling is a term which describes a function, class, or application module which is dependent on particular platforms, frameworks, languages, and libraries. It is a relative term, meaning that our Calculator.java example is tightly coupled to the Java programming language and standard library, but that is the extent of its coupling. Along the same lines, the problem of testing classes which are tightly coupled to the Android platform, is that you must find a way to work with or around the platform.

For classes tightly coupled to the Android platform, you have two options. The first, is to simply deploy your classes to an Android device (physical or virtual). While I do suggest that you test deploy your application code before shipping it to production, this is a highly inefficient approach during the early and middle stages of the development process with respect to time.

A Unit, however technical a definition you prefer, is generally thought of as a single function in a class (although some expand the definition to include subsequent helper functions which are called internally by the initial single function call). Either way, Units are meant to be small; building, compiling, and deploying an entire application to test a single Unit is to miss the point of testing in isolation entirely.

Another solution to the problem of tight coupling, is to use testing frameworks to interact with, or mock (simulate) platform dependencies. Frameworks such as Espresso and Robolectric give developers far more effective means for testing Units than the previous approach; the former being useful for tests run on a device (known as “instrumented tests” because apparently calling them device tests was not ambiguous enough) and the latter being capable of mocking the Android framework locally on a JVM.

Before I proceed to railing against such frameworks instead of the alternative I will discuss shortly, I want to be clear that I do not mean to imply that you should never use these options. The process which a developer uses to build and test their applications should be born of a combination of personal preference and an eye for efficiency.

For those who are not fond of building modular and loosely coupled applications, you will have no choice but to become familiar with these frameworks if you wish to have an adequate level of test coverage. Many wonderful applications have been built this way, and I am not infrequently accused of making my applications too modular and abstract. Whether you take my approach or decide to lean heavily on frameworks, I salute you for putting in the time and effort to test your applications.

Keep Your Frameworks At Arms Length

For the final preamble to the core lesson of this article, it is worth discussing why you might want to have an attitude of minimalism when it comes to using frameworks (and this applies to more than just testing frameworks). The subtitle above is a paraphrase from the magnanimous teacher of software best practices: Robert “Uncle Bob” C. Martin. Of the many gems he has given me since I first studied his works, this one took several years of direct experience to grasp.

Insofar As I understand what this statement is about, the cost of using frameworks is in the time investment required to learn and maintain them. Some of them change quite frequently and some of them do not change frequently enough. Functions become deprecated, frameworks cease to be maintained, and every 6-24 months a new framework arrives to supplant the last. Therefore, if you can find a solution which can be implemented as a platform or language feature (which tend to last much longer), it will tend to be more resistant to changes of the various types mentioned above.

On a more technical note, frameworks such as Espresso and to a lesser degree Robolectric, can never run as efficiently as simple JUnit tests, or even the framework free test from earlier on. While JUnit is indeed a framework, it is tightly coupled to the JVM, which tends to change at a much slower rate than the Android platform proper. Fewer frameworks almost invariably means code which is more efficient in terms of the time it takes to execute and write one or more tests.

From this, you can probably gather that we will now be discussing an approach which will leverage some techniques which allows us to keep the Android platform at arms length; all the while allowing us plenty of code coverage, test efficiency, and the opportunity to still use a framework here or there when the need arises.

The Art Of Architecture

To use a silly analogy, one might think of frameworks and platforms as being like overbearing colleagues who will take over your development process unless you set appropriate boundaries with them. The golden principles of software architecture can give you the general concepts and specific techniques necessary to both create and enforce these boundaries. As we will see in a moment, if you have ever wondered what the benefits of applying software architecture principles in your code truly are, some directly, and many indirectly make your code easier to test.

Separation Of Concerns

Separation Of Concerns is by my estimation the most universally applicable and useful concept in software architecture as a whole (without meaning to say that others should be neglected). Separation of concerns (SOC) can be applied, or completely ignored, across every perspective of software development I am aware of. To briefly summarize the concept, we will look at SOC when applied to classes, but be aware that SOC can be applied to functions through extensive usage of helper functions, and it can be extrapolated to entire modules of an application (“modules” used in the context of Android/Gradle).

If you have spent much time at all researching software architectural patterns for GUI applications, you will likely have come across at least one of: Model-View-Controller (MVC), Model-View-Presenter (MVP), or Model-View-ViewModel (MVVM). Having built applications in every style, I will say upfront that I do not consider any of them to be the single best option for all projects (or even features within a single project). Ironically, the pattern which the Android team presented some years ago as their recommended approach, MVVM, appears to be the least testable in absence of Android specific testing frameworks (assuming you wish to use the Android platform’s ViewModel classes, which I am admittedly a fan of).

In any case, the specifics of these patterns are less important than their generalities. All of these patterns are just different flavours of SOC which emphasize a fundamental separation of three kinds of code which I refer to as: Data, User Interface, Logic.

So, how exactly does separating Data, User Interface, and Logic help you to test your applications? The answer is that by pulling logic out of classes which must deal with platform/framework dependencies into classes which possess little or no platform/framework dependencies, testing becomes easy and framework minimal. To be clear, I am generally talking about classes which must render the user interface, store data in a SQL table, or connect to a remote server. To demonstrate how this works, let us look at a simplified three layer architecture of a hypothetical Android application.

The first class will manage our user interface. To keep things simple, I have used an Activity for this purpose, but I typically opt for Fragments instead as user interface classes. In either case, both classes present similar tight coupling to the Android platform:

public class CalculatorUserInterface extends Activity implements CalculatorContract.IUserInterface {

    private TextView display;
    private CalculatorContract.IControlLogic controlLogic;
    private final String INVALID_MESSAGE = "Invalid Expression.";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        controlLogic = new DependencyProvider().provideControlLogic(this);

        display = findViewById(R.id.textViewDisplay);
        Button evaluate = findViewById(R.id.buttonEvaluate);
        evaluate.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                controlLogic.handleInput('=');
            }
        });
        //..bindings for the rest of the calculator buttons
    }

    @Override
    public void updateDisplay(String displayText) {
        display.setText(displayText);
    }

    @Override
    public String getDisplay() {
        return display.getText().toString();
    }

    @Override
    public void showError() {
        Toast.makeText(this, INVALID_MESSAGE, Toast.LENGTH_LONG).show();
    }
}

As you can see, the Activity has two jobs: First, since it is the entry point of a given feature of an Android application, it acts as a sort of container for the other components of the feature. In simple terms, a container can be thought of as a sort of root class which the other components are ultimately tethered to via references (or private member fields in this case). It also inflates, binds references, and adds listeners to the XML layout (the user interface).

Testing Control Logic

Rather than having the Activity possess a reference to a concrete class in the back end, we have it talk to an interface of type CalculatorContract.IControlLogic. We will discuss why this is an interface in the next section. For now, just understand that whatever is on the other side of that interface is supposed to be something like a Presenter or Controller. Since this class will be controlling interactions between the front-end Activity and the back-end Calculator, I have chosen to call it CalculatorControlLogic:

public class CalculatorControlLogic implements CalculatorContract.IControlLogic {

    private CalculatorContract.IUserInterface ui;
    private CalculatorContract.IComputationLogic comp;

    public CalculatorControlLogic(CalculatorContract.IUserInterface ui, CalculatorContract.IComputationLogic comp) {
        this.ui = ui;
        this.comp = comp;
    }

    @Override
    public void handleInput(char inputChar) {
        switch (inputChar){
            case '=':
                evaluateExpression();
                break;
            //...handle other input events
        }
    }
    private void evaluateExpression() {
        Optional result = comp.computeResult(ui.getDisplay());

        if (result.isPresent()) ui.updateDisplay(result.get());
        else ui.showError();
    }
}

There are many subtle things about the way in which this class is designed that make it easier to test. Firstly, all of its references are either from the Java standard library, or interfaces which are defined within the application. This means that testing this class without any frameworks is an absolute breeze, and it could be done locally on a JVM. Another small but useful tip is that all of the different interactions of this class can be called via a single generic handleInput(...) function. This provides a single entry point to test every behaviour of this class.

Also note that in the evaluateExpression() function, I am returning a class of type Optional<String> from the back end. Normally I would use what functional programmers call an Either Monad, or as I prefer to call it, a Result Wrapper. Whatever stupid name you use, it is an object which is capable of representing multiple different states through a single function call. Optional is a simpler construct which can represent either a null, or some value of the supplied generic type. In any case, since the back end might be given an invalid expression, we want to give the ControlLogicclass some means of determining the result of the backend operation; accounting for both success and failure. In this case, null will represent a failure.

Below is an example test class which has been written using JUnit, and a class which in testing jargon is called a Fake:

public class CalculatorControlLogicTest {

    @Test
    public void validExpressionTest() {

        CalculatorContract.IComputationLogic comp = new FakeComputationLogic();
        CalculatorContract.IUserInterface ui = new FakeUserInterface();
        CalculatorControlLogic controller = new CalculatorControlLogic(ui, comp);

        controller.handleInput('=');

        assertTrue(((FakeUserInterface) ui).displayUpdateCalled);
        assertTrue(((FakeUserInterface) ui).displayValueFinal.equals("10.0"));
        assertTrue(((FakeComputationLogic) comp).computeResultCalled);

    }

    @Test
    public void invalidExpressionTest() {

        CalculatorContract.IComputationLogic comp = new FakeComputationLogic();
        ((FakeComputationLogic) comp).returnEmpty = true;
        CalculatorContract.IUserInterface ui = new FakeUserInterface();
        ((FakeUserInterface) ui).displayValueInitial = "+7+7";
        CalculatorControlLogic controller = new CalculatorControlLogic(ui, comp);

        controller.handleInput('=');

        assertTrue(((FakeUserInterface) ui).showErrorCalled);
        assertTrue(((FakeComputationLogic) comp).computeResultCalled);

    }

    private class FakeUserInterface implements CalculatorContract.IUserInterface{
        boolean displayUpdateCalled = false;
        boolean showErrorCalled = false;
        String displayValueInitial = "5+5";
        String displayValueFinal = "";

        @Override
        public void updateDisplay(String displayText) {
            displayUpdateCalled = true;
            displayValueFinal = displayText;
        }

        @Override
        public String getDisplay() {
            return displayValueInitial;
        }

        @Override
        public void showError() {
            showErrorCalled = true;
        }
    }

    private class FakeComputationLogic implements CalculatorContract.IComputationLogic{
        boolean computeResultCalled = false;
        boolean returnEmpty = false;

        @Override
        public Optional computeResult(String expression) {
            computeResultCalled = true;
            if (returnEmpty) return Optional.empty();
            else return Optional.of("10.0");
        }
    }
}

As you can see, not only can this test suite be executed very rapidly, but it did not take very much time at all to write. In any case, we will now look at some more subtle things which made writing this test class very easy.

The Power Of Abstraction And Dependency Inversion

There are two other important concepts which have been applied to CalculatorControlLogic which have made it trivially easy to test. Firstly, if you have ever wondered what the benefits of using Interfaces and Abstract Classes (collectively referred to as abstractions) in Java are, the code above is a direct demonstration. Since the class to be tested references abstractions instead of concrete classes, we were able to create Fake test doubles for the user interface and back end from within our test class. As long as these test doubles implement the appropriate interfaces, CalculatorControlLogiccould not care less that they are not the real thing.

Secondly, CalculatorControlLogichas been given its dependencies via the constructor (yes, that is a form of Dependency Injection), instead of creating its own dependencies. Therefore, it does not need to be re-written when used in a production or testing environment, which is a bonus for efficiency.

Dependency Injection is a form of Inversion Of Control, which is a tricky concept to define in plain language. Whether you use Dependency Injection or a Service Locator Pattern, they both achieve what Martin Fowler (my favourite teacher on such topics) describes as “the principle of separating configuration from use.” This results in classes which are easier to test, and easier to build in isolation from one another.

Testing Computation Logic

Finally, we come to the ComputationLogic class, which is supposed to approximate an IO device such as an adapter to a remote server, or a local database. Since we need neither of those for a simple calculator, it will just be responsible for encapsulating the logic required to validate and evaluate the expressions we give it:

public class CalculatorComputationLogic implements CalculatorContract.IComputationLogic {

    private final char ADD = '+';
    private final char SUBTRACT = '-';
    private final char MULTIPLY = '*';
    private final char DIVIDE = '/';

    @Override
    public Optional computeResult(String expression) {
        if (hasOperator(expression)) return attemptEvaluation(expression);
        else return Optional.empty();

    }

    private Optional attemptEvaluation(String expression) {
        String delimiter = getOperator(expression);
        Binomial b = buildBinomial(expression, delimiter);
        return evaluateBinomial(b);
    }

    private Optional evaluateBinomial(Binomial b) {
        String result;
        switch (b.getOperatorChar()) {
            case ADD:
                result = Double.toString(b.firstTerm + b.secondTerm);
                break;
            case SUBTRACT:
                result = Double.toString(b.firstTerm - b.secondTerm);
                break;
            case MULTIPLY:
                result = Double.toString(b.firstTerm * b.secondTerm);
                break;
            case DIVIDE:
                result = Double.toString(b.firstTerm / b.secondTerm);
                break;
            default:
                return Optional.empty();
        }
        return Optional.of(result);
    }

    private Binomial buildBinomial(String expression, String delimiter) {
        String[] operands = expression.split(delimiter);
        return new Binomial(
                delimiter,
                Double.parseDouble(operands[0]),
                Double.parseDouble(operands[1])
        );
    }

    private String getOperator(String expression) {
        for (char c : expression.toCharArray()) {
            if (c == ADD || c == SUBTRACT || c == MULTIPLY || c == DIVIDE)
                return "" + c;
        }

        //default
        return "+";
    }

    private boolean hasOperator(String expression) {
        for (char c : expression.toCharArray()) {
            if (c == ADD || c == SUBTRACT || c == MULTIPLY || c == DIVIDE) return true;
        }
        return false;
    }

    private class Binomial {
        String operator;
        double firstTerm;
        double secondTerm;

        Binomial(String operator, double firstTerm, double secondTerm) {
            this.operator = operator;
            this.firstTerm = firstTerm;
            this.secondTerm = secondTerm;
        }

        char getOperatorChar(){
            return operator.charAt(operator.length() - 1);
        }
    }

    }

There is not too much to say about this class since typically there would be some tight coupling to a particular back-end library which would present similar problems as a class tightly coupled to Android. In a moment we will discuss what to do about such classes, but this one is so easy to test that we may as well have a try:

public class CalculatorComputationLogicTest {

    private CalculatorComputationLogic comp = new CalculatorComputationLogic();

    @Test
    public void additionTest() {
        String EXPRESSION = "5+5";
        String ANSWER = "10.0";

        Optional result = comp.computeResult(EXPRESSION);

        assertTrue(result.isPresent());
        assertEquals(result.get(), ANSWER);
    }

    @Test
    public void subtractTest() {
        String EXPRESSION = "5-5";
        String ANSWER = "0.0";

        Optional result = comp.computeResult(EXPRESSION);

        assertTrue(result.isPresent());
        assertEquals(result.get(), ANSWER);
    }

    @Test
    public void multiplyTest() {
        String EXPRESSION = "5*5";
        String ANSWER = "25.0";

        Optional result = comp.computeResult(EXPRESSION);

        assertTrue(result.isPresent());
        assertEquals(result.get(), ANSWER);
    }

    @Test
    public void divideTest() {
        String EXPRESSION = "5/5";
        String ANSWER = "1.0";

        Optional result = comp.computeResult(EXPRESSION);

        assertTrue(result.isPresent());
        assertEquals(result.get(), ANSWER);
    }

    @Test
    public void invalidTest() {
        String EXPRESSION = "Potato";

        Optional result = comp.computeResult(EXPRESSION);

        assertTrue(!result.isPresent());
    }
}

The easiest classes to test, are those which are simply given some value or object, and are expected to return a result without the necessity of calling some external dependencies. In any case, there comes a point where no matter how much software architecture wizardry you apply, you will still need to worry about classes which cannot be decoupled from platforms and frameworks. Fortunately, there is still a way we can employ software architecture to: At worst make these classes easier to test, and at best, so trivially simple that testing can be done at a glance.

Humble Objects And Passive Views

The above two names refer to a pattern in which an object that must talk to low-level dependencies, is simplified so much that it arguably does not need to be tested. I was first introduced to this pattern via Martin Fowler’s blog on variations of Model-View-Presenter. Later on, through Robert C. Martin’s works, I was introduced to the idea of treating certain classes as Humble Objects, which implies that this pattern does not need to be limited to user interface classes (although I do not mean to say that Fowler ever implied such a limitation).

Whatever you choose to call this pattern, it is delightfully simple to understand, and in some sense I believe it is actually just the result of rigorously applying SOC to your classes. While this pattern applies also to back end classes, we will use our user interface class to demonstrate this principle in action. The separation is very simple: Classes which interact with platform and framework dependencies, do not think for themselves (hence the monikers Humble and Passive). When an event occurs, the only thing they do is forward the details of this event to whatever logic class happens to be listening:

//from CalculatorActivity's onCreate() function:
evaluate.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                controlLogic.handleInput('=');
            }
        });

The logic class, which should be trivially easy to test, is then responsible for controlling the user interface in a very fine-grained manner. Rather than calling a single generic updateUserInterface(...) function on the user interface class and leaving it to do the work of a bulk update, the user interface (or other such class) will possess small and specific functions which should be easy to name and implement:

//Interface functions of CalculatorActivity:
        @Override
    public void updateDisplay(String displayText) {
        display.setText(displayText);
    }

    @Override
    public String getDisplay() {
        return display.getText().toString();
    }

    @Override
    public void showError() {
        Toast.makeText(this, INVALID_MESSAGE, Toast.LENGTH_LONG).show();
    }
//…

In principal, these two examples ought to give you enough to understand how to go about implementing this pattern. The object which possesses the logic is loosely coupled, and the object which is tightly coupled to pesky dependencies becomes almost devoid of logic.

Now, at the start of this subsection, I made the statement that these classes become arguably unnecessary to test, and it is important we look at both sides of this argument. In an absolute sense, it is impossible to achieve 100% test coverage by employing this pattern, unless you still write tests for such humble/passive classes. It is also worth noting that my decision to use a Calculator as an example App, means that I cannot escape having a gigantic mass of findViewById(...) calls present in the Activity. Giant masses of repetitive code are a common cause of typing errors, and in the absence of some Android UI testing frameworks, my only recourse for testing would be via deploying the feature to a device and manually testing each interaction. Ouch.

It is at this point that I will humbly say that I do not know if 100% code coverage is absolutely necessary. I do not know many developers who strive for absolute test coverage in production code, and I have never done so myself. One day I might, but I will reserve my opinions on this matter until I have the reference experiences to back them up. In any case, I would argue that applying this pattern will still ultimately make it simpler and easier to test tightly coupled classes; if for no reason other than they become simpler to write.

Another objection to this approach, was raised by a fellow programmer when I described this approach in another context. The objection was that the logic class (whether it be a Controller, Presenter, or even a ViewModel depending on how you use it), becomes a God class.

While I do not agree with that sentiment, I do agree that the end result of applying this pattern is that your Logic classes become larger than if you left more decisions up to your user interface class.

This has never been an issue for me as I treat each feature of my applications as self-contained components, as opposed to having one giant controller for managing multiple user interface screens. In any case, I think this argument holds reasonably true if you fail to apply SOC to your front end or back end components. Therefore, my advice is to apply SOC to your front end and back end components quite rigorously.

Further Considerations

After all of this discussion on applying the principles of software architecture to reduce the necessity of using a wide-array of testing frameworks, improve the testability of classes in general, and a pattern which allows classes to be tested indirectly (at least to some degree), I am not actually here to tell you to stop using your preferred frameworks.

For those curious, I often use a library to generate mock classes for my Unit tests (for Java I prefer Mockito, but these days I mostly write Kotlin and prefer Mockk in that language), and JUnit is a framework which I use quite invariably. Since all of these options are coupled to languages as opposed to the Android platform, I can use them quite interchangeably across mobile and web application development. From time to time (if project requirements demand it), I will even use tools like Robolectric, MockWebServer, and in my five years of studying Android, I did begrudgingly use Espresso once.

My hope is that in reading this article, anyone who has experienced a similar degree of aversion to testing due to paralysis by jargon analysis, will come to see that getting started with testing really can be simple and framework minimal.

Further Reading on SmashingMag:

Smashing Editorial
(dm, il)

Source: Smashing Magazine, Testing Made Easier Via Framework Minimalism And Software Architecture

Testing Made Easier Via Framework Minimalism And Software Architecture

dreamt up by webguru in Uncategorized | Comments Off on Testing Made Easier Via Framework Minimalism And Software Architecture

Testing Made Easier Via Framework Minimalism And Software Architecture

Testing Made Easier Via Framework Minimalism And Software Architecture

Ryan Kay



Like many other Android developers, my initial foray into testing on the platform lead me to be immediately confronted with a demoralizing degree of jargon. Further, what few examples I came across at the time (circa 2015) did not present practical use cases which may have inclined me to think that the cost to benefit ratio of learning a tool like Espresso in order to verify that a TextView.setText(…) was working properly, was a reasonable investment.

To make matters even worse, I did not have a working understanding of software architecture in theory or practice, which meant that even if I bothered to learn these frameworks, I would have been writing tests for monolithic applications comprised of a few god classes, written in spaghetti code. The punchline is that building, testing, and maintaining such applications is an exercise in self-sabotage quite regardless of your framework expertise; yet this realization only becomes clear after one has built a modular, loosely-coupled, and highly-cohesive application.

From here we arrive at one of the main points of discussion in this article, which I will summarize in plain language here: Among the primary benefits of applying the golden principles of software architecture (do not worry, I will discuss them with simple examples and language), is that your code can become easier to test. There are other benefits to applying such principles, but the relationship between software architecture and testing is the focus of this article.

However, for the sake of those who wish to understand why and how we test our code, we will first explore the concept of testing by analogy; without requiring you to memorize any jargon. Before getting deeper into the primary topic, we will also look at the question of why so many testing frameworks exist, for in examining this we may begin to see their benefits, limitations, and perhaps even an alternative solution.

Testing: Why And How

This section will not be new information for any seasoned tester, but perhaps you may enjoy this analogy nonetheless. Of course I am a software engineer, not a rocket engineer, but for a moment I will borrow an analogy which relates to designing and building objects both in physical space, and in the memory space of a computer. It turns out that while the medium changes, the process is in principle quite the same.

Suppose for a moment that we are rocket engineers, and our job is to build the first stage* rocket booster of a space shuttle. Suppose as well, that we have come up with a serviceable design for the first stage to begin building and testing in various conditions.

“First stage” refers to boosters which are fired when the rocket is first launched

Before we get to the process, I would like to point out why I prefer this analogy: You should not have any difficulty answering the question of why we are bothering to test our design before putting it in situations where human lives are at stake. While I will not try to convince you that testing your applications before launch could save lives (although it is possible depending on the nature of the application), it could save ratings, reviews, and your job. In the broadest sense, testing is the way in which we make sure that single parts, several components, and whole systems work before we employ them in situations where it is critically important for them to not fail.

Returning to the how aspect of this analogy, I will introduce the process by which engineers go about testing a particular design: redundancy. Redundancy is simple in principle: Build copies of the component to be tested to the same design specification as what you wish to use at launch time. Test these copies in an isolated environment which strictly controls for preconditions and variables. While this does not guarantee that the rocket booster will work properly when integrated in the whole shuttle, one can be certain that if it does not work in a controlled environment, it will be very unlikely to work at all.

Suppose that of the hundreds, or perhaps thousands of variables which the copies of the rocket design have been tested against, it comes down to ambient temperatures in which the rocket booster will be test fired. Upon testing at 35° Celsius, we see that everything functions without error. Again, the rocket is tested at roughly room temperature without failure. The final test will be at the lowest recorded temperature for the launch site, at -5° Celcius. During this final test, the rocket fires, but after a short period, the rocket flares up and shortly thereafter explodes violently; but fortunately in a controlled and safe environment.

At this point, we know that changes in temperature appear to be at least involved in the failed test, which leads us to consider what parts of the rocket booster may be adversely effected by cold temperatures. Over time, it is discovered that one key component, a rubber O-ring which serves to staunch the flow of fuel from one compartment to another, becomes rigid and ineffectual when exposed to temperatures approaching or below freezing.

It is possible that you have noticed that his analogy is loosely based on the tragic events of the Challenger space shuttle disaster. For those unfamiliar, the sad truth (insofar as investigations concluded) is that there were plenty of failed tests and warnings from the engineers, and yet administrative and political concerns spurred the launch to proceed regardless. In any case, whether or not you have memorized the term redundancy, my hope is that you have grasped the fundamental process for testing parts of any kind of system.

Concerning Software

Whereas the prior analogy explained the fundamental process for testing rockets (while taking plenty of liberty with the finer details), I will now summarize in a manner which is likely more relevant to you and I. While it is possible to test software by only launching it to devices once it is in any sort of deployable state, I suppose instead that we can apply the principle of redundancy to the individual parts of the application first.

This means that we create copies of the smaller parts of the whole application (commonly referred to as Units of software), set up an isolated test environment, and see how they behave based on whatever variables, arguments, events, and responses which may occur at runtime. Testing is truly as simple as that in theory, but the key to even getting to this process lies in building applications which are feasibly testable. This comes down to two concerns which we will look at in the next two sections. The first concern has to do with the test environment, and the second concern has to do with the way in which we structure applications.

Why Do We Need Frameworks?

In order to test a piece of software (henceforth referred to as a Unit, although this definition is deliberately an over-simplification), it is necessary to have some kind of testing environment which allows you to interact with your software at runtime. For those building applications to be executed purely on a JVM (Java Virtual Machine) environment, all that is required to write tests is a JRE (Java Runtime Environment). Take for example this very simple Calculator class:

class Calculator {
    private int add(int a, int b){
        return a + b;
    }

    private int subtract(int a, int b){
        return a - b;
    }
}

In absence of any frameworks, as long as we have a test class which contains a mainfunction to actually execute our code, we can test it. As you may recall, the main function denotes the starting point of execution for a simple Java program. As for what we are testing for, we simply feed some test data into the Calculator’s functions and verify that it is performing basic arithmetic properly:

public class Main {

    public static void main(String[] args){
    //create a copy of the Unit to be tested
        Calculator calc = new Calculator();
    //create test conditions to verify behaviour
        int addTest = calc.add(2, 2);
        int subtractTest = calc.subtract(2, 2);

    //verify behaviour by assertion
        if (addTest == 4) System.out.println("addTest has passed.");
        else System.out.println("addTest has failed.");

        if (subtractTest == 0) System.out.println("subtractTest has passed.");
        else System.out.println("subtractTest has failed.");
    }
}

Testing an Android application is of course, a completely different procedure. Although there is a main function buried deep within the source of the ZygoteInit.java file (the finer details of which are not important here), which is invoked prior to an Android application being launched on the JVM, even a junior Android developer ought to know that the system itself is responsible for calling this function; not the developer. Instead, the entry points for Android applications happen to be the Application class, and any Activity classes which the system can be pointed to via the AndroidManifest.xml file.

All of this is just a lead up to the fact that testing Units in an Android application presents a greater level of complexity, strictly because our testing environment must now account for the Android platform.

Taming The Problem Of Tight Coupling

Tight coupling is a term which describes a function, class, or application module which is dependent on particular platforms, frameworks, languages, and libraries. It is a relative term, meaning that our Calculator.java example is tightly coupled to the Java programming language and standard library, but that is the extent of its coupling. Along the same lines, the problem of testing classes which are tightly coupled to the Android platform, is that you must find a way to work with or around the platform.

For classes tightly coupled to the Android platform, you have two options. The first, is to simply deploy your classes to an Android device (physical or virtual). While I do suggest that you test deploy your application code before shipping it to production, this is a highly inefficient approach during the early and middle stages of the development process with respect to time.

A Unit, however technical a definition you prefer, is generally thought of as a single function in a class (although some expand the definition to include subsequent helper functions which are called internally by the initial single function call). Either way, Units are meant to be small; building, compiling, and deploying an entire application to test a single Unit is to miss the point of testing in isolation entirely.

Another solution to the problem of tight coupling, is to use testing frameworks to interact with, or mock (simulate) platform dependencies. Frameworks such as Espresso and Robolectric give developers far more effective means for testing Units than the previous approach; the former being useful for tests run on a device (known as “instrumented tests” because apparently calling them device tests was not ambiguous enough) and the latter being capable of mocking the Android framework locally on a JVM.

Before I proceed to railing against such frameworks instead of the alternative I will discuss shortly, I want to be clear that I do not mean to imply that you should never use these options. The process which a developer uses to build and test their applications should be born of a combination of personal preference and an eye for efficiency.

For those who are not fond of building modular and loosely coupled applications, you will have no choice but to become familiar with these frameworks if you wish to have an adequate level of test coverage. Many wonderful applications have been built this way, and I am not infrequently accused of making my applications too modular and abstract. Whether you take my approach or decide to lean heavily on frameworks, I salute you for putting in the time and effort to test your applications.

Keep Your Frameworks At Arms Length

For the final preamble to the core lesson of this article, it is worth discussing why you might want to have an attitude of minimalism when it comes to using frameworks (and this applies to more than just testing frameworks). The subtitle above is a paraphrase from the magnanimous teacher of software best practices: Robert “Uncle Bob” C. Martin. Of the many gems he has given me since I first studied his works, this one took several years of direct experience to grasp.

Insofar As I understand what this statement is about, the cost of using frameworks is in the time investment required to learn and maintain them. Some of them change quite frequently and some of them do not change frequently enough. Functions become deprecated, frameworks cease to be maintained, and every 6-24 months a new framework arrives to supplant the last. Therefore, if you can find a solution which can be implemented as a platform or language feature (which tend to last much longer), it will tend to be more resistant to changes of the various types mentioned above.

On a more technical note, frameworks such as Espresso and to a lesser degree Robolectric, can never run as efficiently as simple JUnit tests, or even the framework free test from earlier on. While JUnit is indeed a framework, it is tightly coupled to the JVM, which tends to change at a much slower rate than the Android platform proper. Fewer frameworks almost invariably means code which is more efficient in terms of the time it takes to execute and write one or more tests.

From this, you can probably gather that we will now be discussing an approach which will leverage some techniques which allows us to keep the Android platform at arms length; all the while allowing us plenty of code coverage, test efficiency, and the opportunity to still use a framework here or there when the need arises.

The Art Of Architecture

To use a silly analogy, one might think of frameworks and platforms as being like overbearing colleagues who will take over your development process unless you set appropriate boundaries with them. The golden principles of software architecture can give you the general concepts and specific techniques necessary to both create and enforce these boundaries. As we will see in a moment, if you have ever wondered what the benefits of applying software architecture principles in your code truly are, some directly, and many indirectly make your code easier to test.

Separation Of Concerns

Separation Of Concerns is by my estimation the most universally applicable and useful concept in software architecture as a whole (without meaning to say that others should be neglected). Separation of concerns (SOC) can be applied, or completely ignored, across every perspective of software development I am aware of. To briefly summarize the concept, we will look at SOC when applied to classes, but be aware that SOC can be applied to functions through extensive usage of helper functions, and it can be extrapolated to entire modules of an application (“modules” used in the context of Android/Gradle).

If you have spent much time at all researching software architectural patterns for GUI applications, you will likely have come across at least one of: Model-View-Controller (MVC), Model-View-Presenter (MVP), or Model-View-ViewModel (MVVM). Having built applications in every style, I will say upfront that I do not consider any of them to be the single best option for all projects (or even features within a single project). Ironically, the pattern which the Android team presented some years ago as their recommended approach, MVVM, appears to be the least testable in absence of Android specific testing frameworks (assuming you wish to use the Android platform’s ViewModel classes, which I am admittedly a fan of).

In any case, the specifics of these patterns are less important than their generalities. All of these patterns are just different flavours of SOC which emphasize a fundamental separation of three kinds of code which I refer to as: Data, User Interface, Logic.

So, how exactly does separating Data, User Interface, and Logic help you to test your applications? The answer is that by pulling logic out of classes which must deal with platform/framework dependencies into classes which possess little or no platform/framework dependencies, testing becomes easy and framework minimal. To be clear, I am generally talking about classes which must render the user interface, store data in a SQL table, or connect to a remote server. To demonstrate how this works, let us look at a simplified three layer architecture of a hypothetical Android application.

The first class will manage our user interface. To keep things simple, I have used an Activity for this purpose, but I typically opt for Fragments instead as user interface classes. In either case, both classes present similar tight coupling to the Android platform:

public class CalculatorUserInterface extends Activity implements CalculatorContract.IUserInterface {

    private TextView display;
    private CalculatorContract.IControlLogic controlLogic;
    private final String INVALID_MESSAGE = "Invalid Expression.";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        controlLogic = new DependencyProvider().provideControlLogic(this);

        display = findViewById(R.id.textViewDisplay);
        Button evaluate = findViewById(R.id.buttonEvaluate);
        evaluate.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                controlLogic.handleInput('=');
            }
        });
        //..bindings for the rest of the calculator buttons
    }

    @Override
    public void updateDisplay(String displayText) {
        display.setText(displayText);
    }

    @Override
    public String getDisplay() {
        return display.getText().toString();
    }

    @Override
    public void showError() {
        Toast.makeText(this, INVALID_MESSAGE, Toast.LENGTH_LONG).show();
    }
}

As you can see, the Activity has two jobs: First, since it is the entry point of a given feature of an Android application, it acts as a sort of container for the other components of the feature. In simple terms, a container can be thought of as a sort of root class which the other components are ultimately tethered to via references (or private member fields in this case). It also inflates, binds references, and adds listeners to the XML layout (the user interface).

Testing Control Logic

Rather than having the Activity possess a reference to a concrete class in the back end, we have it talk to an interface of type CalculatorContract.IControlLogic. We will discuss why this is an interface in the next section. For now, just understand that whatever is on the other side of that interface is supposed to be something like a Presenter or Controller. Since this class will be controlling interactions between the front-end Activity and the back-end Calculator, I have chosen to call it CalculatorControlLogic:

public class CalculatorControlLogic implements CalculatorContract.IControlLogic {

    private CalculatorContract.IUserInterface ui;
    private CalculatorContract.IComputationLogic comp;

    public CalculatorControlLogic(CalculatorContract.IUserInterface ui, CalculatorContract.IComputationLogic comp) {
        this.ui = ui;
        this.comp = comp;
    }

    @Override
    public void handleInput(char inputChar) {
        switch (inputChar){
            case '=':
                evaluateExpression();
                break;
            //...handle other input events
        }
    }
    private void evaluateExpression() {
        Optional result = comp.computeResult(ui.getDisplay());

        if (result.isPresent()) ui.updateDisplay(result.get());
        else ui.showError();
    }
}

There are many subtle things about the way in which this class is designed that make it easier to test. Firstly, all of its references are either from the Java standard library, or interfaces which are defined within the application. This means that testing this class without any frameworks is an absolute breeze, and it could be done locally on a JVM. Another small but useful tip is that all of the different interactions of this class can be called via a single generic handleInput(...) function. This provides a single entry point to test every behaviour of this class.

Also note that in the evaluateExpression() function, I am returning a class of type Optional<String> from the back end. Normally I would use what functional programmers call an Either Monad, or as I prefer to call it, a Result Wrapper. Whatever stupid name you use, it is an object which is capable of representing multiple different states through a single function call. Optional is a simpler construct which can represent either a null, or some value of the supplied generic type. In any case, since the back end might be given an invalid expression, we want to give the ControlLogicclass some means of determining the result of the backend operation; accounting for both success and failure. In this case, null will represent a failure.

Below is an example test class which has been written using JUnit, and a class which in testing jargon is called a Fake:

public class CalculatorControlLogicTest {

    @Test
    public void validExpressionTest() {

        CalculatorContract.IComputationLogic comp = new FakeComputationLogic();
        CalculatorContract.IUserInterface ui = new FakeUserInterface();
        CalculatorControlLogic controller = new CalculatorControlLogic(ui, comp);

        controller.handleInput('=');

        assertTrue(((FakeUserInterface) ui).displayUpdateCalled);
        assertTrue(((FakeUserInterface) ui).displayValueFinal.equals("10.0"));
        assertTrue(((FakeComputationLogic) comp).computeResultCalled);

    }

    @Test
    public void invalidExpressionTest() {

        CalculatorContract.IComputationLogic comp = new FakeComputationLogic();
        ((FakeComputationLogic) comp).returnEmpty = true;
        CalculatorContract.IUserInterface ui = new FakeUserInterface();
        ((FakeUserInterface) ui).displayValueInitial = "+7+7";
        CalculatorControlLogic controller = new CalculatorControlLogic(ui, comp);

        controller.handleInput('=');

        assertTrue(((FakeUserInterface) ui).showErrorCalled);
        assertTrue(((FakeComputationLogic) comp).computeResultCalled);

    }

    private class FakeUserInterface implements CalculatorContract.IUserInterface{
        boolean displayUpdateCalled = false;
        boolean showErrorCalled = false;
        String displayValueInitial = "5+5";
        String displayValueFinal = "";

        @Override
        public void updateDisplay(String displayText) {
            displayUpdateCalled = true;
            displayValueFinal = displayText;
        }

        @Override
        public String getDisplay() {
            return displayValueInitial;
        }

        @Override
        public void showError() {
            showErrorCalled = true;
        }
    }

    private class FakeComputationLogic implements CalculatorContract.IComputationLogic{
        boolean computeResultCalled = false;
        boolean returnEmpty = false;

        @Override
        public Optional computeResult(String expression) {
            computeResultCalled = true;
            if (returnEmpty) return Optional.empty();
            else return Optional.of("10.0");
        }
    }
}

As you can see, not only can this test suite be executed very rapidly, but it did not take very much time at all to write. In any case, we will now look at some more subtle things which made writing this test class very easy.

The Power Of Abstraction And Dependency Inversion

There are two other important concepts which have been applied to CalculatorControlLogic which have made it trivially easy to test. Firstly, if you have ever wondered what the benefits of using Interfaces and Abstract Classes (collectively referred to as abstractions) in Java are, the code above is a direct demonstration. Since the class to be tested references abstractions instead of concrete classes, we were able to create Fake test doubles for the user interface and back end from within our test class. As long as these test doubles implement the appropriate interfaces, CalculatorControlLogiccould not care less that they are not the real thing.

Secondly, CalculatorControlLogichas been given its dependencies via the constructor (yes, that is a form of Dependency Injection), instead of creating its own dependencies. Therefore, it does not need to be re-written when used in a production or testing environment, which is a bonus for efficiency.

Dependency Injection is a form of Inversion Of Control, which is a tricky concept to define in plain language. Whether you use Dependency Injection or a Service Locator Pattern, they both achieve what Martin Fowler (my favourite teacher on such topics) describes as “the principle of separating configuration from use.” This results in classes which are easier to test, and easier to build in isolation from one another.

Testing Computation Logic

Finally, we come to the ComputationLogic class, which is supposed to approximate an IO device such as an adapter to a remote server, or a local database. Since we need neither of those for a simple calculator, it will just be responsible for encapsulating the logic required to validate and evaluate the expressions we give it:

public class CalculatorComputationLogic implements CalculatorContract.IComputationLogic {

    private final char ADD = '+';
    private final char SUBTRACT = '-';
    private final char MULTIPLY = '*';
    private final char DIVIDE = '/';

    @Override
    public Optional computeResult(String expression) {
        if (hasOperator(expression)) return attemptEvaluation(expression);
        else return Optional.empty();

    }

    private Optional attemptEvaluation(String expression) {
        String delimiter = getOperator(expression);
        Binomial b = buildBinomial(expression, delimiter);
        return evaluateBinomial(b);
    }

    private Optional evaluateBinomial(Binomial b) {
        String result;
        switch (b.getOperatorChar()) {
            case ADD:
                result = Double.toString(b.firstTerm + b.secondTerm);
                break;
            case SUBTRACT:
                result = Double.toString(b.firstTerm - b.secondTerm);
                break;
            case MULTIPLY:
                result = Double.toString(b.firstTerm * b.secondTerm);
                break;
            case DIVIDE:
                result = Double.toString(b.firstTerm / b.secondTerm);
                break;
            default:
                return Optional.empty();
        }
        return Optional.of(result);
    }

    private Binomial buildBinomial(String expression, String delimiter) {
        String[] operands = expression.split(delimiter);
        return new Binomial(
                delimiter,
                Double.parseDouble(operands[0]),
                Double.parseDouble(operands[1])
        );
    }

    private String getOperator(String expression) {
        for (char c : expression.toCharArray()) {
            if (c == ADD || c == SUBTRACT || c == MULTIPLY || c == DIVIDE)
                return "" + c;
        }

        //default
        return "+";
    }

    private boolean hasOperator(String expression) {
        for (char c : expression.toCharArray()) {
            if (c == ADD || c == SUBTRACT || c == MULTIPLY || c == DIVIDE) return true;
        }
        return false;
    }

    private class Binomial {
        String operator;
        double firstTerm;
        double secondTerm;

        Binomial(String operator, double firstTerm, double secondTerm) {
            this.operator = operator;
            this.firstTerm = firstTerm;
            this.secondTerm = secondTerm;
        }

        char getOperatorChar(){
            return operator.charAt(operator.length() - 1);
        }
    }

    }

There is not too much to say about this class since typically there would be some tight coupling to a particular back-end library which would present similar problems as a class tightly coupled to Android. In a moment we will discuss what to do about such classes, but this one is so easy to test that we may as well have a try:

public class CalculatorComputationLogicTest {

    private CalculatorComputationLogic comp = new CalculatorComputationLogic();

    @Test
    public void additionTest() {
        String EXPRESSION = "5+5";
        String ANSWER = "10.0";

        Optional result = comp.computeResult(EXPRESSION);

        assertTrue(result.isPresent());
        assertEquals(result.get(), ANSWER);
    }

    @Test
    public void subtractTest() {
        String EXPRESSION = "5-5";
        String ANSWER = "0.0";

        Optional result = comp.computeResult(EXPRESSION);

        assertTrue(result.isPresent());
        assertEquals(result.get(), ANSWER);
    }

    @Test
    public void multiplyTest() {
        String EXPRESSION = "5*5";
        String ANSWER = "25.0";

        Optional result = comp.computeResult(EXPRESSION);

        assertTrue(result.isPresent());
        assertEquals(result.get(), ANSWER);
    }

    @Test
    public void divideTest() {
        String EXPRESSION = "5/5";
        String ANSWER = "1.0";

        Optional result = comp.computeResult(EXPRESSION);

        assertTrue(result.isPresent());
        assertEquals(result.get(), ANSWER);
    }

    @Test
    public void invalidTest() {
        String EXPRESSION = "Potato";

        Optional result = comp.computeResult(EXPRESSION);

        assertTrue(!result.isPresent());
    }
}

The easiest classes to test, are those which are simply given some value or object, and are expected to return a result without the necessity of calling some external dependencies. In any case, there comes a point where no matter how much software architecture wizardry you apply, you will still need to worry about classes which cannot be decoupled from platforms and frameworks. Fortunately, there is still a way we can employ software architecture to: At worst make these classes easier to test, and at best, so trivially simple that testing can be done at a glance.

Humble Objects And Passive Views

The above two names refer to a pattern in which an object that must talk to low-level dependencies, is simplified so much that it arguably does not need to be tested. I was first introduced to this pattern via Martin Fowler’s blog on variations of Model-View-Presenter. Later on, through Robert C. Martin’s works, I was introduced to the idea of treating certain classes as Humble Objects, which implies that this pattern does not need to be limited to user interface classes (although I do not mean to say that Fowler ever implied such a limitation).

Whatever you choose to call this pattern, it is delightfully simple to understand, and in some sense I believe it is actually just the result of rigorously applying SOC to your classes. While this pattern applies also to back end classes, we will use our user interface class to demonstrate this principle in action. The separation is very simple: Classes which interact with platform and framework dependencies, do not think for themselves (hence the monikers Humble and Passive). When an event occurs, the only thing they do is forward the details of this event to whatever logic class happens to be listening:

//from CalculatorActivity's onCreate() function:
evaluate.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                controlLogic.handleInput('=');
            }
        });

The logic class, which should be trivially easy to test, is then responsible for controlling the user interface in a very fine-grained manner. Rather than calling a single generic updateUserInterface(...) function on the user interface class and leaving it to do the work of a bulk update, the user interface (or other such class) will possess small and specific functions which should be easy to name and implement:

//Interface functions of CalculatorActivity:
        @Override
    public void updateDisplay(String displayText) {
        display.setText(displayText);
    }

    @Override
    public String getDisplay() {
        return display.getText().toString();
    }

    @Override
    public void showError() {
        Toast.makeText(this, INVALID_MESSAGE, Toast.LENGTH_LONG).show();
    }
//…

In principal, these two examples ought to give you enough to understand how to go about implementing this pattern. The object which possesses the logic is loosely coupled, and the object which is tightly coupled to pesky dependencies becomes almost devoid of logic.

Now, at the start of this subsection, I made the statement that these classes become arguably unnecessary to test, and it is important we look at both sides of this argument. In an absolute sense, it is impossible to achieve 100% test coverage by employing this pattern, unless you still write tests for such humble/passive classes. It is also worth noting that my decision to use a Calculator as an example App, means that I cannot escape having a gigantic mass of findViewById(...) calls present in the Activity. Giant masses of repetitive code are a common cause of typing errors, and in the absence of some Android UI testing frameworks, my only recourse for testing would be via deploying the feature to a device and manually testing each interaction. Ouch.

It is at this point that I will humbly say that I do not know if 100% code coverage is absolutely necessary. I do not know many developers who strive for absolute test coverage in production code, and I have never done so myself. One day I might, but I will reserve my opinions on this matter until I have the reference experiences to back them up. In any case, I would argue that applying this pattern will still ultimately make it simpler and easier to test tightly coupled classes; if for no reason other than they become simpler to write.

Another objection to this approach, was raised by a fellow programmer when I described this approach in another context. The objection was that the logic class (whether it be a Controller, Presenter, or even a ViewModel depending on how you use it), becomes a God class.

While I do not agree with that sentiment, I do agree that the end result of applying this pattern is that your Logic classes become larger than if you left more decisions up to your user interface class.

This has never been an issue for me as I treat each feature of my applications as self-contained components, as opposed to having one giant controller for managing multiple user interface screens. In any case, I think this argument holds reasonably true if you fail to apply SOC to your front end or back end components. Therefore, my advice is to apply SOC to your front end and back end components quite rigorously.

Further Considerations

After all of this discussion on applying the principles of software architecture to reduce the necessity of using a wide-array of testing frameworks, improve the testability of classes in general, and a pattern which allows classes to be tested indirectly (at least to some degree), I am not actually here to tell you to stop using your preferred frameworks.

For those curious, I often use a library to generate mock classes for my Unit tests (for Java I prefer Mockito, but these days I mostly write Kotlin and prefer Mockk in that language), and JUnit is a framework which I use quite invariably. Since all of these options are coupled to languages as opposed to the Android platform, I can use them quite interchangeably across mobile and web application development. From time to time (if project requirements demand it), I will even use tools like Robolectric, MockWebServer, and in my five years of studying Android, I did begrudgingly use Espresso once.

My hope is that in reading this article, anyone who has experienced a similar degree of aversion to testing due to paralysis by jargon analysis, will come to see that getting started with testing really can be simple and framework minimal.

Further Reading on SmashingMag:

Smashing Editorial
(dm, il)

Source: Smashing Magazine, Testing Made Easier Via Framework Minimalism And Software Architecture