Jun 172016
 

Before moving on to Codeception and PHP, we should cover the basics and start by explaining why we need testing in applications in the first place. Perhaps we could complete a project without wasting time on tests, at least this time?

Sure, you don’t need tests for everything; for example, when you want to build yet another homepage. You probably don’t need tests when your project contains static pages linked by one router.

However, you definitely do need testing when:

  • Your team uses BDD/TDD.
  • Your Git repo contains more than a couple commits.
  • You are a proper professional, working on a serious project.

You can excuse yourself by saying that you already have a dedicated test department, a group of people who conduct tests and write new ones when needed. But, can you imagine how long bug fixing will take after you add new functionality to your project?

What Does Testing Solve?

First, let’s decide what sort of problems may be solved through testing. You can’t get rid of all your errors with testing, but you can describe expected behavior in test cases. The errors might be inside your test cases. Spaghetti code remains spaghetti code even when you use test cases.

However, you can be sure that your code will be changed afterward (by fixing errors, or adding new features), so your code still will be free of errors described in the test. Besides, even well-written tests may sometimes be used in documentation because there you can see how typical scenarios unfold and check expected behavior. We can say that testing is a small but crucial investment in the future.

So what sort of tests can we employ?

Basic unit tests usually aren't enough. They need to be backed by integrational, functional, and acceptance testing.

Basic unit tests usually aren’t enough. They need to be backed by integrational, functional, and acceptance testing.
  • Unit tests: Low-level tests that check small pieces of your code – your class’ methods isolated from other code.
  • Integrational testing: Integrational tests check a part of your application, they may contain several classes or methods, but should be restricted to one feature. This test should also check how different classes are interacting.
  • Functional testing: Tests specific requests to your application: browser response, database changes and so on.
  • Acceptance testing: In most cases acceptance testing means checking if the application meets all client requirements.

To clarify, let’s say we illustrate the process with something tangible, such as a building. A building is composed of small blocks that form walls. Each brick has to meet specified requirements; it has to withstand the required load, have a specific volume and shape, and so on. These are unit tests. The idea of integrational tests is to check how tightly and accurately the bricks adhere to each other, how they’re integrated into a certain element of the building. Functional tests can be likened to tests on a single wall of the building, to check whether or not the interior is protected from the elements, and whether or not it possible to see the sun through the window. Acceptance testing involves testing the entire building as a complete product: Open the door, go inside, shut the door, switch on the light, climb to the second floor and take a look at the garden outside the building.

Meet Codeception

However, this division is conditional and sometimes it is difficult to resist the temptation of mixing different kinds of tests.

Many developers use unit tests and claim that’s enough. I used to be one such developer; I found using different systems for different types of tests too difficult and time-consuming. A while ago, I decided to find something more useful than PHPUnit; I wanted to be better at testing my code, but I didn’t want to read and learn tons of documentation and look for pitfalls. That’s how I discovered Codeception. At first, I was skeptical, as we often are when it comes to something new (this project is five years old, so technically, it can’t be considered “new”), but after playing around with it for a couple of days, I concluded Codeception is a very useful and powerful system.

So how do you install Codeception? It is as simple as it gets:

$ composer require "codeception/codeception"
$ php vendor/bin/codecept bootstrap

After installing, you will find a new folder named tests in your project, and there will be some subfolders named acceptance, functional and unit. It looks like we can start writing our tests. Cool, but what’s next?

Now, try to add a standard acceptance Hello World test.

$ php vendor/bin/codecept generate:cept acceptance HelloWorld

Now, we get an acceptance test file tests/acceptance/HelloWorldCept.php, with the following content:

<?php
$I = new AcceptanceTester($scenario);
$I->wantTo('perform actions and see result');

The default variable, named $I, is not just a letter; it is a character. What conducts the tests? The tester, obviously. This tester opens your website’s page or class, does something with it, and shows you the end-result of its actions. You will see what worked and what went wrong. That’s why this object is named $I and why it contains methods called wantTo(), see() or amOnPage().

So, let’s think like a tester would about ways of checking a page’s operability. The first approach is to open the page and search for a phrase. It proves that the page is available to visitors.

This should be easy:

<?php
$I->amOnPage('/');
$I->see('Welcome');

We can use this command to run Codeception’s tests:

$ php vendor/bin/codecept run

We see immediately that something is wrong. At first glance, it appears that the message is too long and unclear, but when we look more closely, everything becomes obvious.

Whops! Something went wrong. That's the whole point of testing. Check out the message, identify the error, and learn from your mistakes.

Whops! Something went wrong. That’s the whole point of testing. Check out the message, identify the error, and learn from your mistakes.

We had one test, Acceptance, and it detected an error:

Acceptance Tests (1)
Perform actions and see result (HelloWorldCept)                                                             Error

----------
1) Failed to perform actions and see result in HelloWorldCept (tests/acceptance/HelloWorldCept .php)
[GuzzleHttp\Exception\ConnectException] cURL error 6: Could not resolve host: localhost (see http://curl.haxx.se/libcurl/c/libcurl-errors.html) 

This is the culprit: localhost is not available.

And here are the scenario steps of our test:

 1. $I->amOnPage("/")

Ok, let’s open tests/acceptance.suite.yml and change url: http://localhost/to something that is actually available. In my case, it is my local test host, url: https://local.codeception-article.com/

Run the test again and this is what you should end up with:

Acceptance Tests (1) ---------------------------------------------------------------------------------------
Perform actions and   result (HelloWorldCept)                                                             Ok

Hooray! Our first successful test!

Of course, amOnPage() is not the only testing method available, we merely singled it out for our example. All Codeception test methods can be divided into the following groups:

  • Interaction with page: fillField(), selectOption(), submitForm(), click()
  • Assertions. see(), dontSee(), seeElement(), seeInCurrentUrl(), seeCheckboxIsChecked(), seeInField(), seeLink(). To all these methods you can add a suffix and use it when you need a method that will not interrupt the test scenario when something cannot be found.
  • Cookie methods: setCookie(), grabCookie(), seeCookie()
  • Comment and description of test scenarios: amGoingTo(), wantTo(), expect(). Use these methods to get well commented and described tests, which will help you remember the goals of the test.

So, if we were to test the password-reset email page, we could do it this way:

<?php
$I = new AcceptanceTester($scenario);
$I->wantTo('Test forgotten password functionality');
$I->amOnPage('/forgotten')
$I->see('Enter email');
$I->fillField('email', 'incorrect@email.com');
$I->click('Continue');
$I->expect('Reset password link not sent for incorrect email');
$I->see('Email is incorrect, try again');
$I->amGoingTo('Fill correct email and get link');
$I->see('Enter email');
$I->fillField('email', 'correct@email.com');
$I->click('Continue');
$I->expect('Reset password link sent for correct email');
$I->see('Please check your email for next instructions');

It looks like this should do it, but what if there are some Ajax-loaded parts on the page? Can we test a page like that? The answer is that Codeception uses PhpBrowser, based on Symfony BrowserKit and Guzzle, by default. It is simple, fast and you need only curl to use it.

You could also use Selenium and test pages with real browsers. Yes, it will be slower, but you will be able to test JavaScript, as well.

First, you need to install the Selenium driver, change acceptance.suite.yml and rebuild the AcceptanceTester class. After this, you can use methods wait() and waitForElement(). And, more interestingly, you will be able to save your time and resources by using methods saveSessionSnapshot() and loadSessionSnapshot(). This method allows you to store the session state and start new tests in earlier sessions. This is useful in some situations, for instance, in the test authorization process.

So, we end up with a simple, yet powerful, ability to test many functions.

Functional Testing

OK, time to move on to functional testing.

$ php vendor/bin/codecept generate:cept functional HelloWorld

And this is what we get:

<?php
$I = new FunctionalTester($scenario);
$I->amOnPage('/');
$I->see('Welcome');

Wait, what?

No, it is not a mistake. Functional tests should be written in the same way as integrational tests. The difference is that functional tests are interacting directly with your application. That means you don’t need a webserver to run functional test, and you have more capacity for testing different parts of your application.

It does mean that support for all frameworks is lacking, but the list of supported frameworks is extensive: Symfony, Silex, Phalcon, Yii, Zend Framework, Lumen, Laravel. This should be sufficient for most cases and most developers. Please consult Codeception’s module documentation to get a list of available functions and then just switch it on in functional.suite.yml.

Codeception supports major frameworks: Symfony, Silex, Phalcon, Yii, Zend Framework, Lumen, Laravel.

Codeception supports major frameworks: Symfony, Silex, Phalcon, Yii, Zend Framework, Lumen, Laravel.

Before we proceed to unit testing, allow me to make a small digression. As you may have noticed, we created our tests with key cept:

$ php vendor/bin/codecept generate: cept acceptance HelloWorld

This is not the only way of creating tests. There are also cest tests. The difference is that you can structure multiple related scenarios in one class:

$ php vendor/bin/codecept generate:cest acceptance HelloWorld
<?php
class HelloWorldCest
{
    public function _before(AcceptanceTester $I)
    {
         $I->amOnPage('/forgotten')
    }

    public function _after(AcceptanceTester $I)
    {
    }

    // tests
    public function testEmailField(AcceptanceTester $I)
    {
	$I->see('Enter email');

    }
    public function testIncorrectEmail(AcceptanceTester $I)
    {
	$I->fillField('email', 'incorrect@email.com');
	$I->click('Continue');
	$I->see('Email is incorrect, try again');
    }
    public function testCorrectEmail(AcceptanceTester $I)
    {
	$I->fillField('email', 'correct@email.com');
	$I->click('Continue');
	$I->see('Please check your email for next instructions');
    }
}

In this example, methods _before() and _after() are run before and after each test. An instance of AcceptanceTester class is passed to each test, so you can use it in the same way as in cest tests. This style of tests can be useful in certain situations, so it is worth keeping in mind.

Unit Testing

Time for some unit testing.

Codeception is based on PHPUnit, so you can use tests written for PHPUnit. To add new PHPUnit tests, use the following approach:

$ php vendor/bin/codecept generate:phpunit unit HelloWorld

Or just inherit your tests on \PHPUnit_Framework_TestCase.

But if you want something more, you should try Codeception’s unit tests:

$ php vendor/bin/codecept generate:test unit HelloWorld
<?php

class HelloWorldTest extends \Codeception\TestCase\Test
{
    /**
     * @var \UnitTester
     */
    protected $tester;

    protected function _before()
    {
    }

    protected function _after()
    {
    }

    // tests
    public function testUserSave()
    {
	$user = User::find(1);
	$user->setEmail('correct@email.com');
	$user->save();
	$user = User::find(1);
	$this->assertEquals('correct@email.com', $user->getEmail());
    }
}

Nothing unusual for now. Methods _before() and _after() are setUp() and tearDown() analogues and will run before and after each test.

The main advantage of this test is in its ability to extend your testing process by including modules that can be switched on in unit.suite.yml:

  • Access to memcache and databases to track changes (MySQL, SQLite, PostgreSQL, MongoDB are supported)
  • Testing of REST/SOAP applications
  • Queues

Each module has its own features, so it is best to check the documentation and collect the necessary information for each module before proceeding to actual tests.

Plus, you can use the Codeception/Specify package (which needs to be added to composer.json) and write a description like so:

<?php 
class HelloWorldTest extends \Codeception\TestCase\Test
{
    use \Codeception\Specify;
    private $user;
    protected function _before()
   {
	$this->user = User::find(1);
   }
    public function testUserEmailSave()
    {
	$this->specify("email can be stored", function() {
            	$this->user->setEmail('correct@email.com');
		$this->user->save();
		$user = User::find(1);
            	$this->assertEquals('correct@email.com', $user->getEmail());
        	});
    }
}

PHP code inside these closure functions is isolated, so changes inside will not affect the rest of your code. Descriptions will help you to make the test more readable and make it easier to identify failed tests.

As an optional extra, you can use package Codeception\Verify for BDD-like syntax:

<?php
public function testUserEmailSave()
{
	verify($map->getEmail())->equals('correct@email.com');
}

And of course you can use stubs:

<?php
public function testUserEmailSave()
{
        $user = Stub::make('User', ['getEmail' => 'correct@email.com']);
        $this->assertEquals('correct@email.com', $user->getEmail());
}

Verdict: Codeception Saves Time And Effort

So what should you expect from Codeception? Who’s it for? Are there any caveats?

Codeception can be employed by developers with vastly different PHP profficiency levels and teams of all sizes.

Codeception can be employed by developers with vastly different PHP profficiency levels and teams of all sizes.

In my opinion, this testing framework is suitable for all sorts of different teams: Large and small, beginners andbattle-hardened PHP professionals, those who are using a popular framework, and those who aren’t using any framework.

In any case, it all boils down to this: Codeception is ready for prime time.

It is a mature and well-documented framework that may easily be extended by numerous modules. Codeception is modern, but based on the time-tested PHPUnit, which should reassure developers who don’t want to experiment too much.

It performs well, which means it’s fast and doesn’t require too much time and effort. Better yet, it is relatively easy to master, and abundant documentation should assist a hassle-free learning process.

Codeception is also easy to install and configure, yet it boasts a lot of advanced options. While most users won’t need all (or indeed, most) of them, it all depends on what you intend to do with it. You can start with the basics, and the extra features will come in handy sooner or later.

This article was written by VASILY KOVAL, a Toptal HTML developer.

Jun 112016
 

What is BEM Methodology?

When you are building smaller websites, how you organize your styles is usually not a big problem. You create your usual files, write all the needed CSS, and that’s all. However, when it comes to larger, more complex projects, how you organize your code becomes crucial. How the code is structured is even more important if you are working in a team consisting of multiple front-end and back-end developers.

BEM Methodology will massively improve code maintainability and speed up the development process

BEM Methodology will massively improve code maintainability and speed up the development process

Today, there are plenty of methodologies with the aim of reducing CSS code and making your CSS code more maintainable. In this article, I am going to explain and provide a few examples of one of them: BEM. BEM stands for Block Element Modifier. The main idea behind it is to speed up the development process, and ease the teamwork of developers by arranging CSS classes into independent modules. If you ever saw a class name like header__form--search, that is BEM in action. Yes, classes can be named very long, but they are all readable and understandable.

Note that the best practice is to use BEM only with classes, and not IDs because classes allow you to repeat names if necessary and create more consistent coding structure. Also, if you want to break your website into organized modules, it should consist of the same structure: block, element, and modifier. Where each block can have multiple elements, and both block and elements can have multiple modifiers. However, let’s first start with the basic BEM structure and explain it with examples.

Block

A block represents an object in your website. Think of it as bigger structural chunks of your code. Most common blocks on every website today are header, content, sidebar, footer, and search. Blocks in BEM are always a starting point of chaining your CSS classes on to. Take a look at a few block examples:

  • a content
  • a menu
  • a search form
.content {/* Styles */}
.menu {/* Styles */}
.search {/* Styles */}

Element

An element is a component within the block that performs a particular function. It should only make sense in the context of its block:

  • a content article
  • a menu item
  • a search input field
.content__article {/* Styles */}
.menu__item {/* Styles */}
.search__input {/* Styles */}

Modifier

A modifier is how we represent the variations of a block. If you’ve ever used Bootstrap, then the best example would be the button sizes. Button sizes are just size variations of the button itself, which makes it the modifier:

  • a content featured article
  • a menu link
  • a search field with or without icon
.content__article--featured {/* Styles */}
.menu__item--link {/* Styles */}
.search__input--icon {/* Styles */}

Naming Conventions

The primary purpose of BEM methodology is to make names of CSS selectors as informative and transparent as possible. Original BEM style is defined in this way:

Block name is usually a single word like .header, but if you have longer block definition then it is divided with a single hyphen -:

.lang-switcher {/* Styles */}

Element name starts with double underscore __:

.lang-switcher__flag {/* Styles */}

Modifier name starts with single underscore _:

.lang-switcher__flag_basic {/* Styles */}

There is only one very critical rule in BEM methodology – a modifier cannot be used outside of the context of its owner.

Example:

.btn_big {/* Styles */}

You can use btn_big only if header is defined also.

Bad example:

<div class=”btn_big”>...</div>

Good example:

<div class=”btn btn_big”>...</div>

Beside these original BEM styles, there are alternative naming schemes like Harry Roberts and CamelCase styles.

Harry Roberts style example:

.block-name__element-name--modifier-name {/* Styles */}

CamelCase style example:

.BlockName__ElementName_ModifierName {/* Styles */}

There are few others too, but these two are the most common ones. Personally, I am a fan of the naming convention proposed by Harris Roberts, which has the following rules:

  • Names are written in lowercase
  • Words within the names of BEM entities are separated by a hyphen -
  • An element name is separated from a block name by a double underscore __
  • Boolean modifiers are delimited by double hyphens --
  • Key-value type modifiers are not used

The reason why this naming convention is much better formed than others is that you can easily distinguish modifier element from others. In original naming conventions, modifier would be defined like this:

.block__element_modifier {/* Styles */}

But as you can see, there is not very much difference between a single and double underscore. On the other hand, double hyphen provides clean separation, and you can see the modifier instantly:

.block__element--modifier {/* Styles */}

BEM Example in Different Formats

Please note that besides CSS, BEM is also very useful in organizing your JSON, XML, tree files, or any format supports nesting. Think of BEM methodology as a good way to build your UI.

HTML structured in BEM format

Let’s consider the following HTML, structured in BEM format:

<header class=”header”>
  <img class=”header__logo”>
  <form class=”header__search-from”>
    <input class=”header__search-from__input” type=”input”>
    <button class=”header__search-from__button” type=”button”>
  </form>
  <div class=”header__lang-switcher”></div>
</header>

The same can be achieved using JSON and XML format.

XML:

<block:header>
  <block:logo/>
  <block:search-from>
    <block:input/>
    <block:button/>
  </block>
  <block:lang-switcher/>
</block>

JSON:

{
  block: ‘header’,
  content: [
    { block: ‘logo’ },
    {
      block: ‘search-form’,
      content: [
        { block: ‘input’ },
        { block: ‘button’ }
      ]
    },
    { block: ‘lang-switcher’ }
  ]
}

File System Organization of a BEM Project

In BEM, it is critical to organize your files in a correct manner. Not only is BEM providing you a great organization of CSS classes and making them completely understandable, but also gives you a very maintainable file structure. Let’s take an example project, using BEM file organization technique with SASS files:

blocks/
  input/
    __box/
      --big/
        input__box--big.scss
      input__box.scss
  button/
    --big/
      button--big.scss

As you can see above, just by seeing the subfolder structure inside your main folder, everything is clear and organized. In this way, it makes no difference who is working after you or if you are working after someone, because it is incredibly easy to follow the same pattern.

Dividing BEM Project into Platforms

Besides just organizing your files using BEM methodology techniques, you can also go into more specific things. For example, if you are building a web project which is going to be fully responsive, and the client specified that some blocks on the mobile are totally different than on desktop devices, it would be best to divide your BEM folder structure into platforms. Example of organizing buttons on various platforms:

common.blocks/
  button/
    button.scss
desktop.blocks/
  button/
    buttons.scss
mobile.blocks/
  button/
    button.scss

Note that this is just an example if you want to organize your whole project using BEM methodology. File tree with BEM structure is not mandatory to use BEM correctly, you can use BEM just in some segments of the project. So far I haven’t been using this strict BEM file structure organization where every element and modifier has its file created. Instead, I am just creating a file structure for blocks which are having a declaration of its elements and modifiers.

Tree Organization of a BEM Project

BEM in Practice

Since you are now familiar with naming conventions, I will demonstrate BEM methodology in practice. Let’s say that we have this HTML code in action:

<a class=”btn btn--big btn--primary-colorhref=”#” title=”Title”>
  <span class=”btn__price”>$3.99</span>
  <span class=”btn__text”>Product</span>
</a>

With the following CSS markup applied:

.btn__price {/* Styles */}

.btn__text {/* Styles */}

.btn--big {/* Styles */}

.btn--primary-color {/* Styles */}

Now, don’t be mislead. In our examples so far we almost always had a block, element, and modifier, which doesn’t always have to be the case.

For example, let’s say we have a block named person. A person has legs and hands, it can also be female or male. If we want to define a male person with a right hand it will look like this:

.person--male__hand--right {/* Styles */}

Now you can see the real meaning of the BEM. We defined a person which modifier is a gender. Since it doesn’t matter if a person is male or female, it has a hand, and hand is an element. And again, each person can have right or left hand which is again a modifier.

In another case, if we want to define general person with a single hand, we will do it like this:

.person__hand {/* Styles */}

As you can notice, once you get comfortable with BEM it’s very easy to structure your CSS and HTML structure with it.

Using BEM with CSS Preprocessors

Personally, I can not imagine starting any new project without using one of the CSS preprocessors. As you all know, preprocessors are a great thing and they are providing us a lot of benefits, and most importantly they are a perfect match with BEM methodology.

In the following example, you can see the most typical example of BEM, in combination with SASS:

.person {
  &__hand {/* Styles */}

  &__leg {/* Styles */}

  &--male {
    /* Styles */

    &__hand {
      /* Styles */

      &--left {/* Styles */}

      &--right {/* Styles */}
    }

    &__leg {
      /* Styles */

      &--left {/* Styles */}

      &--right {/* Styles */}
    }
  }

  &--female {
    /* Styles */

    &__hand {
      /* Styles */

      &--left {/* Styles */}

      &--right {/* Styles */}
    }

    &__leg {
      /* Styles */

      &--left {/* Styles */}

      &--right {/* Styles */}
    }
  }
}

SASS code will compile into the following CSS:

.person__hand {/* Styles */}

.person__leg {/* Styles */}

.person--male {/* Styles */}

.person--male__hand {/* Styles */}

.person--male__hand--left {/* Styles */}

.person--male__hand--right {/* Styles */}

.person--male__leg {/* Styles */}

.person--male__leg--left {/* Styles */}

.person--male__leg--right {/* Styles */}

.person--female {/* Styles */}

.person--female__hand {/* Styles */}

.person--female__hand--left {/* Styles */}

.person--female__hand--right {/* Styles */}

.person--female__leg {/* Styles */}

.person--female__leg--left {/* Styles */}

.person--female__leg--right {/* Styles */}

If you want to go even further, you can use a handy SASS mixins for BEM:

/// Block Element
/// @param {String} $element - Element's name
@mixin element($element) {
    &__#{$element} {
        @content;
    }
}

/// Block Modifier
/// @param {String} $modifier - Modifier's name
@mixin modifier($modifier) {
    &--#{$modifier} {
        @content;
    }
}

And you can use it like this:

.person {
  @include element('hand') {/* Person hand */}

  @include element('leg') {/* Person leg */}

  @include modifier('male') {
    /* Person male */
    
    @include element('hand') {
      /* Person male hand */
      @include modifier('left') {
        /* Person male left hand */
      }
      @include modifier('right') {
        /* Person male right hand */
      }
    }
  }
}

Which will produce the following CSS output:

.person__hand {
  /* Person hand */
}

.person__leg {
  /* Person leg */
}

.person--male {
  /* Person male */
}

.person--male__hand {
  /* Person male hand */
}

.person--male__hand--left {
  /* Person male left hand */
}

.person--male__hand--right {
  /* Person male right hand */
}

I know that most likely you won’t have a use case this long, but this is a great example of how BEM is used and why it’s so powerful, both in small and large scale projects.

Starting Your BEM Project

As explained in the official BEM documentation, the easiest way to start you own new BEM project is to use existing GIT repository. Simply use Git clone command:

$ git clone https://github.com/bem/project-stub.git

Next, go to a newly created directory and install all dependencies:

$ npm install

All required dependencies will be installed:

BEM dependencies

Build the project using ENB:

$ node_modules/.bin/enb make

Run a server mode for development:

$ node_modules/.bin/enb server

As a result, the following message appears:

Server started at 0.0.0.0:8080

Now, this means that the server is up and running. You can now check the results on this address:

http://localhost:8080/desktop.bundles/index/index.html

As you can see, there are a lot of elements already created which are defined inside bemjson file which is located here:

project-stub/desktop.bundles/index/index.bemjson.js

You can see and explore the current structure of the file that is generating all that HTML, which you see at your localhost index.html file. We are going to alter this file to get our “Person” BEM project which we explained in a previous chapter. You can remove (or comment) the whole code from index.bemjson.js file, and replace it with this one:

module.exports = {
    block: 'page',
    title: 'Person BEM',
    favicon : '/favicon.ico',
    head : [
        { elem : 'meta', attrs : { name : 'description', content : '' } },
        { elem : 'meta', attrs : { name : 'viewport', content : 'width=device-width, initial-scale=1' } },
        { elem : 'css', url : 'index.min.css' }
    ],
    scripts: [{ elem : 'js', url : 'index.min.js' }],
    content: [
        {
            block: 'person',
            content: [
                {
                    elem: 'male',
                    content: [
                        {
                            elem: 'leg',
                            mods: {side: 'left'},
                            content: 'Male person leg -- left'
                        },
                        {
                            elem: 'leg',
                            mods: {side: 'right'},
                            content: 'Male person leg -- right'
                        },
                        {
                            elem: 'hand',
                            mods: {side: 'left'},
                            content: 'Male person hand -- left'
                        },
                        {
                            elem: 'hand',
                            mods: {side: 'right'},
                            content: 'Male person hand -- right'
                        }
                    ]
                },
                {
                    elem: 'female',
                    content: [
                        {
                            elem: 'leg',
                            mods: {side: 'left'},
                            content: 'Female person leg -- left'
                        },
                        {
                            elem: 'leg',
                            mods: {side: 'right'},
                            content: 'Female person leg -- right'
                        },
                        {
                            elem: 'hand',
                            mods: {side: 'left'},
                            content: 'Female person hand -- left'
                        },
                        {
                            elem: 'hand',
                            mods: {side: 'right'},
                            content: 'Female person hand -- right'
                        }
                    ]
                },
            ]
        }
    ]
};

Now, the following HTML will be generated:

<div class="person">
    <div class="person__male">
        <div class="person__leg person__leg_side_left">
          Male person leg -- left
        </div>

        <div class="person__leg person__leg_side_right">
          Male person leg -- right
        </div>

        <div class="person__hand person__hand_side_left">
          Male person hand -- left
        </div>

        <div class="person__hand person__hand_side_right">
          Male person hand -- right
        </div>
    </div>

    <div class="person__female">
        <div class="person__leg person__leg_side_left">
          Female person leg -- left
        </div>

        <div class="person__leg person__leg_side_right">
          Female person leg -- right
        </div>

        <div class="person__hand person__hand_side_left">
          Female person hand -- left
        </div>

        <div class="person__hand person__hand_side_right">
          Female person hand -- right
        </div>
    </div>
</div>

As you can see from the code above, the default BEM coding scheme was used in this scenario since we are just using default settings which BEM provided to us. There are a lot more commands and options which you can explore and use, such as creating new pages, blocks, or modifying BEM HTML. I will not go too deep into this, and it can all be found in the official BEM documentation.

BEM Advantages and Concerns

Advantages and Concerns

Advantages

  • BEM is excellent for maintaining. How many times have you had to work after someone on a large scaled project and you are just too afraid to change anything without something unknown collapsing? When using BEM, you know the exact purpose of the element and in which block it may appear.
  • Class names are logical and intuitive, and every member of the team knows what that element does on the website. BEM gives everyone on a project a declarative syntax they can share so they’re on the same page.
  • BEM eliminates nested CSS selectors. Every single HTML element has its own CSS class, and by its name you know what its purpose is. One selector to rule them all.

Concerns and Common Mistakes

  • Do not go too deep into nesting. The main rule should be not to use more than two levels of parent and child.
  • Be careful with where you start your block scope. A common mistake here is when a developer is using block, but he is not realising that at the later point of development that same block will have main parent block which will possibly break the rule with nesting.
  • Avoid SASS @extend. To quote Harry Roberts on this:

You can create a greater number of combinations in the view by not ‘tying’ classes together in Sass. The HTML has a much better paper trail in that you can see every class acting on a piece of the DOM. Your CSS stays much slimmer in that you don’t have to create new placeholder classes (or the manifest classes that combine them) every time you want to create a new piece of UI.

Conclusion

When I saw BEM coding scheme for the first time, my first thought was:

These classes are just too long to write and read.

But after giving it a try, now I can not imagine starting a new project without using it. For me, BEM massively improved my code maintainability, and I can for sure say that every developer who is going to be “thrown” into the BEM-based project will catch up really quickly with the whole code structure.

Despite all this, there’s a lot of discussion on social networks about BEM. Some say BEM isn’t good, wondering why they should write such long name classes instead of just use default HTML nested elements. Well, no one says that you must like BEM, but the fact is that the majority of front-end developers embrace it and find it extraordinary useful.

The original article is found on Toptal. Find more CSS resources here.

Jun 112016
 

Although the title UI Designer suggests a sort of departure from the traditional graphic designer, UI design is still a part of the historical trajectory of the visual design discipline.

With each movement or medium, the discipline has introduced new graphic languages, layouts, and design processes. Between generations, the designer has straddled the transition from press to xerox, or paper to pixel. Across these generations, graphic design has carried out the responsibility of representing the visual language of each era respectively.

Therefore, as UI Design makes the transition out of its infancy, what sort of graphic world can we expect to develop? Unfortunately, based on the current trajectory, the future may look bleak. Much of UI Design today has become standardized and repeatable. Design discussions online involve learning the rules to get designs to safely work, rather than push the envelope, or imagine new things. The tendency for UI Designers to resort to patterns and trends has not only created a bland visual environment, but also diminished the value of the designer as processes become more and more formulaic. The issue is precisely not one of technicalities, but of impending visual boredom.

Thus, the Top Five Common UI Design mistakes are:

  • Following Design Rules
  • Abusing the Grid
  • Misunderstanding Typefaces
  • Patterns and the Standardization of UI Design
  • Finding Safety in Contrast

UI Design Rule Book

Understand principles and be creative within their properties. Following the rules will only take your where others have been.

Common Mistake #1: UI Designers Follow the Rules

The world of graphic design has always followed sets of rules and standards. Quite often in any design discipline, the common mistakes that are made can closely coincide with a standard rule that has been broken. Thus, from this perspective the design rules seem to be pretty trustworthy to follow.

However, in just about any design discipline, new design movements and creative innovation has generally resulted from consciously breaking said rule book. This is possible because design is really conditional, and requires the discretion of the designer, rather than a process with any sort of finite answers. Therefore, the design rules should likely be considered as guidelines more so rather than hard and fast rules. The experienced designer knows and respects the rule book just enough to be able break the box.

Unfortunately, the way that design is often discussed online is within sets of do’s and don’ts. Top mistakes and practices for design in 10 easy steps! Design isn’t so straightforward, and requires a much more robust understanding of principles and tendencies, rather than checklists to systematically carry out.

The concern is that if designers were to cease ‘breaking the rules’, then nothing new creatively would ever be made. If UI designers only develop their ability to follow guidelines, rather than make their own decisions, then they may quickly become irrelevant. How else will we argue a value greater than off the shelf templates?

Be Wary of Top Ten Design Rules

The issue with design rules in today’s UI design community is they are so abundant. In the interest of solving any problem, the designer can look to the existing UI community and their set of solutions, rather than solve an issue on their own. However, the abundance of these guides and rules have made themselves less credible.

A google search for “Top UI Design Mistakes” yields a half million search results. So, what are the chances that most, if any of these authors of various articles agree with one another? Or, will each design tip that is discussed coincide accurately with the design problems of a reader?

Often the educational articles online discuss acute problems, rather than the guiding design principles behind the issue. The result is that new designers will never learn why design works the way that it does. Instead, they only become able to copy what has come before. Isn’t it concerning that in none of these sorts of articles is something like play encouraged?

The designer should have a tool kit of principles to guide them, rather than a book of rules to follow predetermined designs. Press x for parallax scrolling and y for carousels. Before choosing, refer to most recent blog post on which navigational tool is trending. Boring!

Trends are like junk food for designers. Following trends produces cheap designs that may offer some initial pay back, but little worth in the long run. This means that not only may trendy designers become dated, or ineffective quickly. But, for you the designer, don’t expect to experience any sense of reward when designing in this way. Although working to invent your own styles and systems is a lot of work, it’s so worth it day in and day out. There’s just something about copying that never seems to feed the soul.

Common Mistake #2: Allowing the Grid to Restrict UI Design

Despite my treatise against rules – here’s a rule: there is no way for a UI Designer to design without a grid. The web or mobile interface is fundamentally based on a pixel by pixel organization – there’s no way around it. However, this does not necessarily mean that the interface has to restrict designers to gridded appearances, or even gridded processes.

Using the Grid as a Trendy Tool

Generally, making any design moves as a response to trends can easily lead to poor design. Perhaps what results is a satisfactory, mostly functional product. But it will almost certainly be boring or uninteresting. To be trendy is to be commonplace. Therefore, when employing the grid in a design, understand what the grid has to offer as a tool, and what it might convey. Grids generally represent neutrality, as everything within the restraints of a grid appear equal. Grids also allow for a neutral navigational experience. Users can jump from item to item without any interference from the designer’s curatorial hand. Whereas, with other navigational structures, the designer may be able to group content, or establish desired sequences.

UI Design Rule Book

Although a useful tool, the grid can be very limiting to designers.

Defaulting to the Grid as a Work Flow

Dylan Fracareta, faculty of RISD and director of PIN-UP Magazine, points out that “most people start off with a 12 – column grid…because you can get 3 and 4 off of that”. The danger here is that immediately the designer predetermines anything that they might come up with. Alternatively, Fracareta resides to only using the move tool with set quantities, rather than physically placing things against a grid line. Although this establishes order, it opens up more potential for unexpected outcomes. Although designing for the browser used to mean that we would input some code, wait, and see what happens. Now, web design has returned to a more traditional form of layout designer that’s “more like adjusting two sheets of transparent paper”. How can we as designers benefit from this process? Working Without a Grid Although grids can be restricting, they are one of our most traditional forms of organization. The grid is intuitive. The grid is neutral and unassuming. Therefore, grids allow content to speak for itself, and for users to navigate at their will and with ease. Despite my warnings towards the restrictiveness of grids, different arrays allow for different levels of guidance or freedom.

Common Mistake #3:The Standardization of UI Design with Patterns

The concept of standardized design elements predates UI design. Architectural details have been frequently repeated in practice for typical conditions for centuries. Generally this practice makes sense for certain parts of a building that are rarely perceived by a user. However, once architects began to standardize common elements like furniture dimensions, or handrails heights, people eventually expressed disinterest in the boring, beige physical environment that resulted. Not only this, but standardized dimensions were proven to be ineffective, as although generated as an average, they didn’t really apply to the majority of the population. Thus, although repeatable detail have their place, they should be used critically.

If we as designers choose to automate, what value are we providing?

If we as designers choose to automate, what value are we providing?

Designers Using the Pattern as Product

Many UI designers don’t view the pattern as a time saving tool, but rather an off the shelf solution to design problems. Patterns are intended to take recurring tasks or artefacts and standardize them in order to make the designer’s job easier. Instead, certain patterns like F Pattern Layouts, Carousels or Pagination have become the entire structure of many of our interfaces.

Justification for the Pattern is Skewed

Designers tell themselves that the F shaped pattern exists as a result of the way that people read on the web.Espen Brunborg points out that perhaps people read this way as a result of us designing for that pattern. “What’s the point of having web designers if all they do is follow the recipe,” Brunborg asks.

Common Mistake #4: Misunderstanding Typefaces

Many designer’s quick tips suggest hard and fast rules about fonts as well. Each rule is shouted religiously, “One font family only! Monospaced fonts are dead! Avoid thin fonts at all costs!”. But really, the only legitimate rules on type, text and fonts should be to enforce legibility, and convey meaning. As long as type is legible, there may very well be an appropriate opportunity for all sorts of typefaces. The UI Designer must take on the responsibility of knowing the history, uses, and designed intentions for each font that they implement in a UI.

Consider a Typeface Only for Legibility

Typefaces convey meaning as well as affect legibility. With all of the discussion surrounding rules for proper legibility on devices etc, designers are forgetting that type is designed to augment a body of text with a sensibility, as much as it is meant to be legible. Legibility is critical, I do not dispute this – but my point is that legibility really should be an obvious goal. Otherwise, why wouldn’t we have just stopped at Helvetica, or maybe Highway Gothic. However, the important thing to remember is that fonts are not just designed for different contexts of legibility. Typefaces are also essential for conveying meaning or giving a body of text a mood.

Typefaces are each designed for their own uses. Don’t allow narrow minded rules to restrict an exploration of the world of type.

Avoiding Thin Fonts At All Costs

Now that the trend has come (and almost gone?), a common design criticism is to avoid thin fonts entirely. In the same way thin fonts came as a trend, they may leave as one also. However, the hope should be to understand the principles of the typefaces rather than follow trends at all.

Some say that they’re impossible to read or untrustworthy between devices. All legitimate points. Yet, this represents a condition in the current discussion of UI design. The font choice is only understood by designers as technical choice in regards to legibility, rather than also understanding the meaning and value of typefaces. The concern is that if legibility is the only concern that a designer carried, would thin fonts be done away with entirely?

Understand why you are using a thin font, and within what contexts. Bold, thick text is actually much more difficult to read at length than thinner fonts. Yet, as bold fonts carry more visual weight they’re more appropriate for headings, or content with little text. As thin fonts are often serifs, its suitability for body text is entirely objective. As serif characters flow together when read in rapid succession, they make for much more comfortable long reading.

As well, thin fonts are often chosen because they convey elegance. So, if a designer was working on an interface for a client whose mandate was to convey elegance, they might find themselves hard pressed to find a heavy typeface to do the job.

Not Enough Variation

A common mistake is to not provide enough variation between fonts in an interface. Changing fonts is a good navigational tool to establish visual hierarchy, or potentially different functions within an interface. A crash course on hierarchy will teach you that generally the largest items, or boldest fonts, should be the most important, and carry the most visual weight. Visual importance can convey content headings, or perhaps frequently used functions.

Too Much Variation

A common UI Design mistake is to load in several different typefaces from different families that each denote a unique function. The issue with making every font choice special, when there is many fonts, is that no font stands out. Changing fonts is a good navigational tool to establish visual hierarchy, or potentially different functions within an interface. Therefore, if every font is different, there is too much confusion for a user to recognize any order.

Common Mistake #5: Under/Over Estimating the Potential of Contrast

A common mistake that appears on many Top UI Design Mistake lists is that designers should avoid low contrast interfaces. There are many instances in which low contrast designs are illegible and ineffective – true. However, as with the previous points, my worry is that this use of language alternatively produces a high contrast design culture in response.

Defaulting to High Contrast

The issue is that high contrast is aesthetically easy to achieve. High contrast visuals are undeniably stimulating or exciting. However, there are many more moods in the human imagination to convey or communicate with, other than high stimulation. To be visually stimulating may also be visually safe.

The same issue is actually occurring in sci-fi film. The entire industry has resorted to black and neon blue visuals as a way to trick viewers into accepting ‘exciting’ visuals, instead of new, creative, or beautiful visuals. This article points out what the sci-fi industry is missing out on by producing safe visuals.

Functionally, if every element in an interface is in high contrast to another, then nothing stands out. This defeats the potential value of contrast as a hierarchical tool. Considering different design moves as tools, rather than rules to follow is essential in avoiding stagnant, trendy design.

Illegibly Low Contrast

The use of low contrast fonts and backgrounds is a commonly made mistake. However, rather than being a design issue. This could potentially be discussed as a beta testing mistake, rather than a design mistake.

How the design element relates as a low contrast piece to the rest of the interface is a design concern. The issue could be that the most significant item hierarchically is low in contrast to the rest of the interface. For the interface to communicate its organizational structure, the elements should contrast one another in a certain way. This is a design discussion. Whether or not it is legible is arguably a testing mistake.

The point is that in only discussing contrast as a technical issue resolvable by adjusting a value, designers miss out on the critical understanding of what contrast is principally used for.

Conclusion

As with the previous 4 mistakes, the abuse of patterns will rarely result in a dysfunctional website, but rather just a boring one. The mistake is in being safe. This overly cautious method of design may not cause the individual project to fail. However, this series of safe mistakes performed by the greater web community can mean greater failures beyond the individual UI design project. The role of the designer should be to imagine, thoughtfully experiment and create – not to responsibly follow rules and guidelines.

The original article was written by KENT MUNDLE – TECHNICAL EDITOR @ TOPTAL and can be read here.

Apr 212016
 

The mobile app market is saturated with competition. Trends turn over quickly, but no niche can last very long without several competitors jumping onto the bandwagon. These conditions result in a high failure rate across the board for the mobile app market. Only 20% of downloaded apps see users return after the first use, whereas 3% of apps remain in use after a month.

If any part of an app is undesirable, or slow to get the hang of, users are more likely to install a new one, rather than stick it out with the imperfect product. Nothing is wasted for the consumer when disposing of an app – except for the efforts of the designers and developers, that is. So, why is it that so many apps fail? Is this a predictable phenomenon that app designers and developers should accept? For clients, is this success rate acceptable? What does it take to bring your designs into the top 3% of prosperous apps?

The common mistakes span from failing to maintain consistency throughout the lifespan of an app, to attracting users in the first place. How can apps be designed with intuitive simplicity, without becoming repetitive and boring? How can an app offer pleasing details, without losing sight of a greater purpose? Most apps live and die in the first few days, so here are the top ten most common mistakes that designers can avoid.

Only 3% of mobile apps are in use after being downloaded.

Only 3% of mobile apps are in use after being downloaded.

Common Mistake #1: A Poor First Impression

Often the first use, or first day with an app, is the most critical period to hook a potential user. The first impression is so critical that it could be an umbrella point for the rest of this top ten. If anything goes wrong, or appears confusing or boring, potential users are quickly disinterested. Although, the proper balance for first impressions is tricky to handle. In some cases, a lengthy onboarding, or process to discover necessary features can bores users. Yet, an instantly stimulating app may disregard the need for a proper tutorial, and promote confusion. Find the balance between an app that is immediately intuitive, but also introduces the users to the most exciting, engaging features quickly. Keep in mind that when users are coming to your app, they’re seeing it for the first time. Go through a proper beta testing process to learn how others perceive your app from the beginning. What seems obvious to the design team, may not be for newcomers.

Improper Onboarding

Onboarding is the step by step process of introducing a user to your app. Although it can be a good way to get someone quickly oriented, onboarding can also be a drawn out process that stands in the way of your users and their content. Often these tutorials are too long, and are likely swiped through blindly.

Sometimes, users have seen your app used in public or elsewhere, such that they get the point and just want to jump in. So, allow for a sort of quick exit strategy to avoid entirely blocking out the app upon its first use. To ensure that the onboarding process is in fact effective, consider which values this can communicate and how. The onboarding process should demonstrate the value of the app in order to hook a user, rather than just an explanation.

Go easy on the intro animation

Some designers address the issue of a good first impression with gripping intro animations to dazzle new users. But, keep in mind that every time someone wants to run the app, they’re going to have to sit through the same thing over and over. If the app serves a daily function, then this will tire your users quickly. Ten seconds of someone’s day for a logo to swipe across the screen and maybe spin a couple times don’t really seem worth it after a while.

Common Mistake #2: Designing an App Without Purpose

Avoid entering the design process without succinct intentions. Apps are often designed and developed in order to follow trends, rather than to solve a problem, fill a niche, or offer a distinct service. What is the ambition for the app? For the designer and their team, the sense of purpose will affect every step of a project. This sensibility will guide each decision from the branding or marketing of an app, to the wireframe format, and button aesthetic. If the purpose is clear, each piece of the app will communicate and function as a coherent whole. Therefore, have the design and development team continually consider their decisions within a greater goal. As the project progresses, the initial ambition may change. This is okay, as long as the vision remains coherent.

Conveying this vision to your potential users means that they will understand what value the app brings to their life. Thus, this vision is an important thing to communicate in a first impression. The question becomes how quickly can you convince users of your vision for the app? How it will improve a person’s life, or provide some sort of enjoyment or comfort. If this ambition is conveyed quickly, then as long as your app is in fact useful, it will make it into the 3%.

Often joining a pre-existing market, or app niche, means that there are apps to study while designing your own. Thus, be careful how you choose to ‘re-purpose’ what is already out there. Study the existing app market, rather than skimming over it. Then, improve upon existing products with intent, rather than thoughtlessly imitating.

Common Mistake #3: Missing Out On UX Design Mapping

Be careful not to skip over a thoughtful planning of an app’s UX architecture before jumping into design work. Even before getting to a wireframing stage, the flow and structure of an app should be mapped out. Designers are often too excited to produce aesthetics and details. This results in a culture of designers who generally under appreciate UX, and the necessary logic or navigation within an app. Slow down. Sketch out the flow of the app first before worrying too much about the finer brush strokes. Often apps fail from an overarching lack of flow and organization, rather than imperfect details. However, once the design process takes off always keep the big picture in mind. The details and aesthetic should then clearly evoke the greater concept.

Common Mistake #4: Disregarding App Development Budget

As soon as the basis of the app is sketched, this is a good time to get a budget from the development team. This way you don’t reach the end of the project and suddenly need to start cutting critical features. As your design career develops, always take note of the average costs of constructing your concepts so that your design thinking responds to economic restraints. Budgets should be useful design constraints to work within.

Many failed apps try to cram too many features in from launch.

Many failed apps try to cram too many features in from launch.

Common Mistake #5: Cramming in Design Features

Hopefully, rigorous wireframing will make the distinction between necessary and excessive functions clear. The platform is already the ultimate swiss army knife, so your app doesn’t need to be. Not only will cramming an app with features lead to a likely disorienting User Experience, but an overloaded app will also be difficult to market. If the use of the app is difficult to explain in a concise way, it’s likely trying to do too much. Paring down features is always hard, but it’s necessary. Often, the best strategy might be to gain trust in the beginning with a single or few features, then later in the life of the app can new ones be ‘tested’. This way, the additional features are less likely to interfere with the crucial first few days of an apps’ life.

Common Mistake #6: Dismissing App Context

Although the conditions of most design offices practically operate within a vacuum, app designers must be aware of wider contexts. Although purpose and ambition are important, they become irrelevant if not directed within the proper context. Remember that although you and your design team may know your app very well, and find its interfacing obvious, this may not be the case for first time users, or different demographics.

Consider the immediate context or situation in which the app is intended to be used. Given the social situation, how long might the person expect to be on the app for? What else might be helpful for them to stumble upon given the circumstance? For example, UBER’s interface excels at being used very quickly. This means that for the most part, there isn’t much room for other content. This is perfect because when a user is out with friends and needing to book a ride, your conversation is hardly interrupted in the process. UBER hides a lot of support content deep within the app, but it only appears once the scenario calls for it.

Who is the target audience for the app? How might the type of user affect how the design of the app? Perhaps, consider that an app targeted for a younger user may be able to take more liberties in assuming a certain level of intuition from the user. Whereas, many functions may need to be pointed out for a less tech savvy user. Is your app meant to be accessed quickly and for a short period of time? Or, is this an app with lots of content that allows users to stay a while? How will the design convey this form of use?

A good app design should consider the context in which it is used.

A good app design should consider the context in which it is used.

Common Mistake #7: Underestimating Crossing Platforms

Often apps are developed quickly as a response to changing markets or advancing competitors. This often results in web content being dragged into the mobile platform. A constant issue, which you’d think would be widely understood by now, is that often apps and other mobile content make poor transitions between the desktop, or mobile platforms. No longer can mobile design get away with scaling down web content in the hope of getting a business quickly into the mobile market. The web to mobile transition doesn’t just mean scaling everything down, but also being able to work with less. Functions, navigation and content must all be conveyed with a more minimal strategy. Another common issue appears when an app developing team aspires to release a product simultaneously on all platforms, and through different app stores. This often results in poor compatibility, or a generally buggy, unpolished app.The gymnastics of balancing multiple platforms may be too much to add onto the launch of an app. However, it doesn’t hurt to sometimes take it slowly with one OS at a time, and iron out the major issues, before worrying about compatibility between platforms.

Common Mistake #8: Overcomplicating App Design

The famous architect Mies Van der Rohe once said, “It’s better to be good than to be unique”. Ensure that your design is meeting the brief before you start breaking the box or adding flourishes. When a designer finds themselves adding things in order to make a composition more appealing or exciting, these choices will likely lack much value. Continue to ask throughout the design process, how much can I remove? Instead of designing additively, design reductively. What isn’t needed? This method is directed as much towards content, concept and function as it is aesthetics. Over complexity is often a result of a design unnecessarily breaking conventions. Several symbols and interfaces are standard within our visual and tactile language. Will your product really benefit from reworking these standards? Standard icons have proven themselves to be universally intuitive. Thus, they are often the quickest way to provide visual cues without cluttering a screen. Don’t let your design flourishes get in the way of the actual content, or function of the app. Often, apps are not given enough white space. The need for white space is a graphic concept that has transcended both digital and print, thus it shouldn’t be underrated. Give elements on the screen room to breath so that all of the work you put into navigation and UX can be felt.

The app design process can be reductive, rather than additive.

The app design process can be reductive, rather than additive.

Common Mistake #9: Design Inconsistencies

To the point on simplicity, if a design is going to introduce new standards, they have to at least be consistent across the app. Each new function or piece of content doesn’t necessarily have to be an opportunity to introduce a new design concept. Are texts uniformly formatted? Do UI elements behave in predictable, yet pleasing ways throughout the app? Design consistency must find the balance between existing within common visual language, as well as avoiding being aesthetically stagnant. The balance between intuitive consistency and boredom is a fine line.

Common Mistake #10: Under Utilizing App Beta Testing

All designers should analyze the use of their apps with some sort of feedback loop in order to learn what is and isn’t working. A common mistake in testing is for a team to do their beta testing in-house. You need to bring in fresh eyes in order to really dig into the drafts of the app. Send out an ad for beta testers and work with a select audience before going public. This can be a great way to iron out details, edit down features, and find what’s missing. Although, beta testing can be time consuming, it may be a better alternative to developing an app that flops. Anticipate that testing often takes 8 weeks for some developers to do it properly. Avoid using friends or colleagues as testers as they may not criticize the app with the honesty that you need. Using app blogs or website to review your app is another way to test the app in a public setting without a full launch. If you’re having a hard time paring down features for your app, this is a good opportunity to see what elements matter or not.

The app design market is a battleground, so designing products which are only adequate just isn’t enough. Find a way to hook users from the beginning – communicate, and demonstrate the critical values and features as soon as you can. To be able to do this, your design team must have a coherent vision of what the app is hoping to achieve. In order to establish this ambition, a rigorous story-boarding process can iron out what is and isn’t imperative. Consider which types of users your app may best fit with. Then refine and refine until absolutely nothing else can be taken away from the project without it falling apart.

The original article was written by KENT MUNDLE – TECHNICAL EDITOR @ TOPTAL and is found on the Toptal Design Blog.

Apr 212016
 

JavaScript: More than meets the eye

JavaScript can seem like a very easy language to learn at first. Perhaps it’s because of its flexible syntax. Or perhaps it’s because of its similarity to other well known languages like Java. Or perhaps it’s because it has so few data types in comparison to languages like Java, Ruby, or .NET.

But in truth, JavaScript is much less simplistic and more nuanced than most developers initially realize. Even for developers with more experience, some of JavaScript’s most salient features continue to be misunderstood and lead to confusion. One such feature is the way that data (property and variable) lookups are performed and the JavaScript performance ramifications to be aware of.

In JavaScript, data lookups are governed by two things: prototypal inheritance and scope chain. As a developer, clearly understanding these two mechanisms is essential, since doing so can improve the structure, and often the performance, of your code.

Property lookups through the prototype chain

When accessing a property in a prototype-based language like JavaScript, a dynamic lookup takes places that involves different layers within the object’s prototypal tree.

In JavaScript, every function is an object. When a function is invoked with the new operator, a new object is created. For example:

function Person(firstName, lastName) {
  this.firstName = firstName;
  this.lastName = lastName;
}

var p1 = new Person('John', 'Doe');
var p2 = new Person('Robert', 'Doe');

In the above example, p1 and p2 are two different objects, each created using the Person function as a constructor. They are independent instances of Person, as demonstrated by this code snippet:

console.log(p1 instanceof Person); // prints 'true'
console.log(p2 instanceof Person); // prints 'true'
console.log(p1 === p2);            // prints 'false'

Since JavaScript functions are objects, they can have properties. A particularly important property that each function has is called prototype.

prototype, which is itself an object, inherits from its parent’s prototype, which inherits from its parent’s prototype, and and so on. This is often referred to as the prototype chain. Object.prototype, which is always at the end of the prototype chain (i.e., at the top of the prototypal inheritance tree), contains methods like toString(), hasProperty(), isPrototypeOf(), and so on.

The relationship between JavaScript prototype and the scope chain is important

Each function’s prototype can be extended to define its own custom methods and properties.

When you instantiate an object (by invoking the function using the new operator), it inherits all the properties in the prototype of that function. Keep in mind, though, that those instances will not have direct access to the prototype object but only to its properties. For example:

// Extending the Person prototype from our earlier example to
// also include a 'getFullName' method:
Person.prototype.getFullName = function() {
  return this.firstName + ' ' + this.lastName;
}

// Referencing the p1 object from our earlier example
console.log(p1.getFullName());            // prints 'John Doe'
// but p1 can’t directly access the 'prototype' object...
console.log(p1.prototype);                // prints 'undefined'
console.log(p1.prototype.getFullName());  // generates an error

There’s an important and somewhat subtle point here: Even if p1 was created before the getFullNamemethod was defined, it will still have access to it because its prototype is the Person prototype.

(It is worth noting that browsers also store a reference to the prototype of any object in a __proto__ property, but it’s really bad practice to directly access the prototype via the __proto__ property, since it’s not part of the standard ECMAScript Language Specification, so don’t do it!)

Since the p1 instance of the Person object doesn’t itself have direct access to the prototype object, if we want overwrite getFullName in p1, we would do so as follows:

// We reference p1.getFullName, *NOT* p1.prototype.getFullName,
// since p1.prototype does not exist:

p1.getFullName = function(){
  return 'I am anonymous';
}

Now p1 has its own getFullName property. But the p2 instance (created in our earlier example) does nothave any such property of its own. Therefore, invoking p1.getFullName() accesses the getFullName method of the p1 instance itself, while invoking p2.getFullName() goes up the prototype chain to the Personprototype object to resolve getFullName:

console.log(p1.getFullName()); // prints 'I am anonymous'
console.log(p2.getFullName()); // prints 'Robert Doe'

See how P1 and P2 relate to the Person prototype in this JavaScript prototype example.

Another important thing to be aware of is that it’s also possible to dynamically change an object’s prototype. For example:

function Parent() {
  this.someVar = 'someValue';
};

// extend Parent’s prototype to define a 'sayHello' method
Parent.prototype.sayHello = function(){
    console.log('Hello');
};

function Child(){
  // this makes sure that the parent's constructor is called and that
  // any state is initialized correctly. 
  Parent.call(this);
};

// extend Child's prototype to define an 'otherVar' property...
Child.prototype.otherVar = 'otherValue';

// ... but then set the Child's prototype to the Parent prototype
// (whose prototype doesn’t have any 'otherVar' property defined,
//  so the Child prototype no longer has ‘otherVar’ defined!)
Child.prototype = Object.create(Parent.prototype);

var child = new Child();
child.sayHello();            // prints 'Hello'
console.log(child.someVar);  // prints 'someValue'
console.log(child.otherVar); // prints 'undefined' 

When using prototypal inheritance, remember to define properties in the prototype after having either inherited from the parent class or specified an alternate prototype.

This diagram shows an example of the relationship between JavaScript prototypes in a prototype chain.

To summarize, property lookups through the JavaScript prototype chain work as follows:

  • If the object has a property with the given name, that value is returned. (The hasOwnProperty method can be used to check if an object has a particular named property.)
  • If the object does not have the named property, the object’s prototype is checked
  • Since the prototype is an object as well, if it does not contain the property either, its parent’s prototype is checked.
  • This process continues up the prototype chain until the property is found.
  • If Object.prototype is reached and it does not have the property either, the property is considered undefined.

Understanding how prototypal inheritance and property lookups work is important in general for developers but is also essential because of its (sometimes significant) JavaScript performance ramifications. As mentioned in the documentation for V8 (Google’s open source, high performance JavaScript engine), most JavaScript engines use a dictionary-like data structure to store object properties. Each property access therefore requires a dynamic look-up in that data structure to resolve the property. This approach makes accessing properties in JavaScript typically much slower than accessing instance variables in programming languages like Java and Smalltalk.

Variable lookups through the scope chain

Another lookup mechanism in JavaScript is based on scope.

To understand how this works, it’s necessary to introduce the concept of execution context.

In JavaScript, there are two types of execution contexts:

  • Global context, created when a JavaScript process is launched
  • Local context, created when a function is invoked

Execution contexts are organized into a stack. At the bottom of the stack, there is always the global context, that is unique for each JavaScript program. Each time a function is encountered, a new execution context is created and pushed onto the top of the stack. Once the function has finished executing, its context is popped off the stack.

Consider the following code:

// global context
var message = 'Hello World';

var sayHello = function(n){
  // local context 1 created and pushed onto context stack
  var i = 0;
  var innerSayHello = function() {
    // local context 2 created and pushed onto context stack
    console.log((i + 1) + ':  ' + message);
    // local context 2 popped off of context stack
  }
  for (i = 0; i < n; i++) {
    innerSayHello();
  }
  // local context 1 popped off of context stack
};

sayHello(3);
// Prints:
// 1:  Hello World
// 2:  Hello World
// 3:  Hello World

Within each execution context is a special object called a scope chain which is used to resolve variables. A scope chain is essentially a stack of currently accessible scopes, from the most immediate context to the global context. (To be a bit more precise, the object at the top of the stack is called an Activation Object which contains references to the local variables for the function being executed, the named function arguments, and two “special” objects: this and arguments.) For example:

The way the scope chain relates to the objects is outlined in this JavaScript example.

Note in the above diagram how this points to the window object by default and also how the global context contains examples of other objects such as console and location.

When attempting to resolve variables via the scope chain, the immediate context is first checked for a matching variable. If no match is found, the next context object in the scope chain is checked, and so on, until a match is found. If no match is found, a ReferenceError is thrown.

It is important to also note that a new scope is added to the scope chain when a try-catch block or a withblock is encountered. In either of these cases, a new object is created and placed at top of the scope chain:

function Person(firstName, lastName) {
    this.firstName = firstName;
    this.lastName = lastName;
};

function persist(person) {
  with (person) {
    // The 'person' object was pushed onto the scope chain when we
    // entered this "with" block, so we can simply reference
    // 'firstName' and 'lastName', rather than person.firstName and
    // person.lastName
    if (!firstName) {
      throw new Error('FirstName is mandatory');
    }
    if (!lastName) {
      throw new Error('LastName is mandatory');
    }
  }
  try {
    person.save();
  } catch(error) {
    // A new scope containing the 'error' object is accessible here
    console.log('Impossible to store ' + person + ', Reason: ' + error);
  }
}

var p1 = new Person('John', 'Doe');
persist(p1);

To fully understand how scope-based variable lookups occur, it is important to keep in mind that in JavaScript there are currently no block-level scopes. For example:

for (var i = 0; i < 10; i++) {
  /* ... */
}
// 'i' is still in scope!
console.log(i);  // prints '10'

In most other languages, the code above would lead to an error because the “life” (i.e., scope) of the variable i would be restricted to the for block. In JavaScript, though, this is not the case. Rather, i is added to the activation object at the top of the scope chain and it will stay there until that object is removed from the scope, which happens when the corresponding execution context is removed from the stack. This behavior is known as variable hoisting.

It is worth noting, though, that support for block-level scopes is making its way into JavaScript through the new let keyword. The let keyword is already available in JavaScript 1.7 and is slated to become an officially supported JavaScript keyword as of ECMAScript 6.

JavaScript Performance Ramifications

The way that property and variable lookups, using prototype chain and scope chain respectively, work in JavaScript is one of the language’s key features, yet it is one of the trickiest and most subtle to understand.

The lookup operations we’ve described in this example, whether based on the prototype chain or the scope chain, are repeated every time a property or variable is accessed. When this lookup occurs within loops or other intensive operations, it can have significant JavaScript performance ramifications, especially in light of the single-threaded nature of the language which prevents multiple operations from happening concurrently.

Consider the following example:

var start = new Date().getTime();
function Parent() { this.delta = 10; };

function ChildA(){};
ChildA.prototype = new Parent();
function ChildB(){}
ChildB.prototype = new ChildA();
function ChildC(){}
ChildC.prototype = new ChildB();
function ChildD(){};
ChildD.prototype = new ChildC();
function ChildE(){};
ChildE.prototype = new ChildD();

function nestedFn() {
  var child = new ChildE();
  var counter = 0;
  for(var i = 0; i < 1000; i++) {
    for(var j = 0; j < 1000; j++) {
      for(var k = 0; k < 1000; k++) {
        counter += child.delta;
      }
    }
  }
  console.log('Final result: ' + counter);
}

nestedFn();
var end = new Date().getTime();
var diff = end - start;
console.log('Total time: ' + diff + ' milliseconds');

In this example, we have a long inheritance tree and three nested loops. Inside the deepest loop, the counter variable is incremented with the value of delta. But delta is located almost at the top of the inheritance tree! This means that each time child.delta is accessed, the full tree needs to be navigated from bottom to top. This can have a really negative impact on performance.

Understanding this, we can easily improve performance of the above nestedFn function by using a local delta variable to cache the value in child.delta (and thereby avoid the need for repetitive traversal of the entire inheritance tree) as follows:

function nestedFn() {
  var child = new ChildE();
  var counter = 0;
  var delta = child.delta;  // cache child.delta value in current scope
  for(var i = 0; i < 1000; i++) {
    for(var j = 0; j < 1000; j++) {
      for(var k = 0; k < 1000; k++) {
        counter += delta;  // no inheritance tree traversal needed!
      }
    }
  }
  console.log('Final result: ' + counter);
}

nestedFn();
var end = new Date().getTime();
var diff = end - start;
console.log('Total time: ' + diff + ' milliseconds');

Of course, this particular technique is only viable in a scenario where it is known that the value of child.deltawon’t change while the for loops are executing; otherwise, the local copy would need to be updated with the current value.

OK, let’s run both versions of the nestedFn method and see if there is any appreciable performance difference between the two.

We’ll start by running the first example in a node.js REPL:

diego@alkadia:~$ node test.js 
Final result: 10000000000
Total time: 8270 milliseconds

So that takes about 8 seconds to run. That’s a long time.

Now let’s see what happens when we run the optimized version:

diego@alkadia:~$ node test2.js 
Final result: 10000000000
Total time: 1143 milliseconds

This time it took just one second. Much faster!

Note that use of local variables to avoid expensive lookups is a technique that can be applied both for property lookup (via the prototype chain) and for variable lookups (via the scope chain).

Moreover, this type of “caching” of values (i.e., in variables in the local scope) can also be beneficial when using some of the most common JavaScript libraries. Take jQuery, for example. jQuery supports the notion of “selectors”, which are basically a mechanism for retrieving one or more matching elements in the DOM. The ease with which one can specify selectors in jQuery can cause one to forget how costly (from a performance standpoint) each selector lookup can be. Accordingly, storing selector lookup results in a local variable can be extremely beneficial to performance. For example:

// this does the DOM search for $('.container') "n" times
for (var i = 0; i < n; i++) {
    $('.container').append(“Line “+i+”<br />”);
}

// this accomplishes the same thing...
// but only does the DOM search for $('.container') once,
// although it does still modify the DOM "n" times
var $container = $('.container');
for (var i = 0; i < n; i++) {
    $container.append("Line "+i+"<br />");
}

// or even better yet...
// this version only does the DOM search for $('.container') once
// AND only modifies the DOM once
var $html = '';
for (var i = 0; i < n; i++) {
    $html += 'Line ' + i + '<br />';
}
$('.container').append($html);

Especially on a web page with a large number of elements, the second approach in the code sample above can potentially result in significantly better performance than the first.

Wrap-up

Data lookup in JavaScript is quite different than it is in most other languages, and it is highly nuanced. It is therefore essential to fully and properly understand these concepts in order to truly master the language. Data lookup and other common JavaScript mistakes should be avoided whenever possible. This understanding is likely to yield cleaner, more robust code that achieves improved JavaScript performance.

The original article was written by DIEGO CASTORINA – SOFTWARE ENGINEER @ TOPTAL and can be read here.

If you’d like to find more resources on Toptal designers or hire a Toptal designer, check this out.