A little fun with Javascript

Just playing around with the spread operator and I found a neat little design pattern I think I am going to work in:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
let testArr = [9,1, 2, 6, 3, 4];
const newMax = (arr) => {
  if(arr.length === 1) { return console.log('end')};
  var [a, ...arr] = arr;
  let max = Math.max(a,...arr);
  console.log(max ,' >=', ...arr);
  newMax(arr);
}
newMax(testArr);
//output
9 ' >=' 1 2 6 3 4
6 ' >=' 2 6 3 4
6 ' >=' 6 3 4
6 ' >=' 3 4
4 ' >=' 4
end

Seems a fun way to look for edges like in the water trap toy problem? I am not sure, but it will be fun to play around with it.

Another thing that used to annoy me was how you had to use string concatenation. It just looked so ugly. I finally (okay I am late to the party) started using backticks for multi-line parties!

1
2
3
4
5
6
7
8
var motion = `Le mouvement de lacet sur la berge des chutes du fleuve,
Le gouffre à l’étambot,
La célérité de la rampe,
L’énorme passade du courant
Mènent par les lumières inouïes
Et la nouveauté chimique
Le voyageurs entourés des trombes du val
Et du strom.`

And finally a little more fun with the spread operator (thanks Alex Rauschmayer) but you can make an array only contain unique values in a very clean, native way.

1
2
3
4
const arr = [7, 3, 1, 3, 3, 7];
[...new Set(arr)]
//returns
[ 7, 3, 1 ]

Front Ends… who needs em!

I have always preferred to work on the back end. It seems more peaceful there. The front end is all colors, moving stuff, and clicks!! Why should I care about clicks… I respond to requests no clickity click click demands! I am fine seeing JSON shoved on the screen, I will parse it visually, personally. I don’t need fancy filters, sorters and interfaces for data.

This opinion puts me most certainly in the minority, so as every good developer does, I forced myself to do something that made me uncomfortable, make a front end. A little background, the project is a way for me to organize my interviews. I needed a place to hold the questions, let me run through them, add notes, and rate the candidate etc.

The api was written with hapijs, my new personal favorite node framework. I was waffling about what to choose for the client side of things. I have already built a few things with Angular 1.5 so I was contemplating Angular 2, but that would go against the reason I am doing this in the first place. I mean if I am going to go out of my comfort zone, it might as well be way out. I could do it in pure vanilla js, but again I am quite familiar with that.. Come on John! Think… think… A-ha! React. I hear about it constantly. It seems to solve some issues with rendering speeds. It has cool terms like ShadowDOM and JSX that remind me of hackers and superbikes in a cyberpunk movie.

ShadowDOM leapt, turning mid-air. Using a neural link to control JSX superbike, it started just before her ass slammed into the seat and exploded violently forward…”

I am a few days in now. I have the basic CRUD working, and you know what? I don’t hate it! I like the way react apps come together. Nice and modular, with plenty of opportunity to build reusable components, really fun stuff. So I guess the lesson learned is to keep yourself confused and uncomfortable. Sounds like fun!

 

Publishing an NPM Module Part 6

These are my notes based on the phenomenal tutorial by Kent C. Dodds hosted by egghead.io both of which are my go to sources when I want to learn something new. I highly suggest you sign up for the pro subscription.

Part 1 | Part 2 | Part 3 | Part 4 | Part 5 | >Part 6 | Part 7

Part 6: Adding ES6 Support

We need to add babel-cli to our dev dependencies:

$ npm i -D babel-cli
glyphicons-28-search  The Docs 
Common uses:
babel -w -o  //watch for file changes and output
babel src -o  // compile entire src dir and concat
babel src -d lib //compile entire src dir and output to lib
babel --ignore  //add this to ignore files i.e. tests

Next we will add a build script for babel. Looking in our node_modules/bin we can see babel has been added making it available to npm for scripts. Let’s edit our package.json to include:

"build": "babel --out-dir dist src”

Now let’s test it to see what gets generated when we run our script. In your terminal run:

$ npm run build

Look in the dist directory and you will see that it was created and files were moved over. It also added our test files! This is something we don’t want to push to the dist since if we test when we publish, not when we consume. We can solve this by adding an ignore flag:

“build”: ''babel --out-dir dist --ignore *.test.js src"

Since this creates a dist directory with files in it, we want to make sure that if we make a change in a filename that the old one is not present in the next build in order to delete the directory cleanly we will add a prebuild script to package.json

"prebuild": "rm -rf dist”

However this is only *nix supported in order to allow windows devs to use this we must add a new dev package called rimraf  a cross-platform rm -rf built for node.

$ npm i -D rimraf

replace rm-rf with rimraf:

"prebuild": "rimraf dist”

now convert to es6 i.e.:

glyphicons-424-git-create
 
'use strict'
//require external dependencies
import uniqueRandomArray from 'unique-random-array';
import _ from 'lodash';

//define available data
import firstNames from '../data/first-names.json';
import middleNames from '../data/middle-names.json';
import lastNames from '../data/last-names.json';

//random generators
let randomFirstName = uniqueRandomArray(firstNames);
let randomMiddleName = uniqueRandomArray(middleNames);
let randomLastName = uniqueRandomArray(lastNames);

//filter functions
const filteredNames = function (nameList, initial) {
 return nameList.filter(function (name) {
 return name[0] === initial;
 })
};

//methods
const list = ()=>{
 let allNames = ["FirstName MiddleName LastName"];
 for (var i = 0; i < firstNames.length; i++) {
 //Math.floor((Math.random() * 10) + 1);
 var tmpName = randomFirstName() + ' ' + randomMiddleName() + ' ' + randomLastName();
 allNames.push(tmpName);
 }
 return allNames;
};


const single = ()=>{
 return randomFirstName() + ' ' + randomMiddleName() + ' ' + randomLastName();
};

const startsWithLetter = (f, m, l)=>{
 var firstName = _.sample(filteredNames(firstNames, f));
 var middleName = _.sample(filteredNames(middleNames, m));
 var lastName = _.sample(filteredNames(lastNames, l));
 return firstName + ' ' + middleName + ' ' + lastName;
}

const numberOfNames = (number=1, allNames=[])=>{
 for (var i = 0; i < number; i++) {
 var tmpName = randomFirstName() + ' ' + randomMiddleName() + ' ' + randomLastName();
 allNames.push(tmpName);
 }
 return allNames;
}

//available methods
module.exports = {
 list: list,
 single: single,
 startsWithLetter: startsWithLetter,
 numberOfNames: numberOfNames
}

Now lets run our build script again:

$ npm run build

Now let’s take a look at index.js in dist and notice nothing happened! That is because really all we did was have it copy it over. We did not tell it to do anything! So we need to install some presets to tell babel how to do the transpiling:

npm i -D babel-preset-es2015 babel-preset-stage-2
glyphicons-28-search Learn more about presets

In order for babel to know about these presets we have added we need to change our package.json to reflect this:

"babel": {
  "presets": [
    "es2015",
    "stage-2"
  ]
}

 

 

We need to change our package.json file to point to dist now:

"main": "dist/index.js",

While we are here we should update the build script by adding –copy-files:

"build:main": "babel --copy-files --out-dir dist --ignore *.test.js src",

 

Now we need to make sure the build script runs before the publish script. We do this by modifying the .travis.yml file scripts section, after check-coverage add:

- npm run build

Now we need to do a little verification on our changes. Let’s run a command to see what will actually be published:

$ npm pack   

A file was generated ending in tgz. Open that up and take a peek. It looks alright, but there are just some extra files in there that we might not need or want. So let’s learn how to limit what gets packed up. We do this by adding a files section to our package.json file:

"files": [
  "dist",
  "data",
  "README.md"
],

  Now that we are writing in ES6 we want to make sure that all of the other pieces are able to work with the new syntax as well. Let’s start with istanbul. It turns out we need a replacement package for that called nyc.

$ npm i -D nyc

Now we need to update package.json to use this new method:

glyphicons-424-git-create
"check-coverage": "nyc check-coverage --statements 100 --branches 100 --functions 100 --lines 100",

Next in the test with the watch command (-w) we want to add in something that will transpile our code. 

"test:watch": "mocha src/index.test.js --compilers js:babel-register -w",

Since we are using it we might as well install it!

npm i -D babel-register

The tests are getting a little clunky, with a lot of repeated code so we are going to clean things up a bit. by letting the watch test just fire off the regular test adding in a -w flag.

"test:watch": "npm t -- -w",
"test": "mocha src/index.test.js --compilers js:babel-register",

Note the double dash in the watch script. This allows you to send in the watch flag to the previous call as if it were in the original.  Since we are cleaning things up let’s go a little farther, but adding a cover script.

"cover": "nyc --reporter=lcov npm t",

We now need to adjust our githook. 

"config": {
  "ghooks": {
    "pre-commit": "npm run cover && npm run check-coverage"
  }

One more spot in .travis.yml we need to make sure we run our cover script so it ends up looking like:

script:
  - npm run cover
  - npm run check-coverage
  - npm run build

 

There we go! We now have an es6 friendly set up!

Next… UMD Build!

glyphicons-55-clock  = Time Saving Idea

glyphicons-499-sunglasses = Pro Tip

glyphicons-31-pencil = Note

glyphicons-197-exclamation-sign = Alert

glyphicons-424-git-create = Code Update

glyphicons-28-search  = A Closer Look

Publishing an NPM Module Part 5

These are my notes based on the phenomenal tutorial by Kent C. Dodds hosted by egghead.io both of which are my go to sources when I want to learn something new. I highly suggest you sign up for the pro subscription.

Part 1 | Part 2 | Part 3 | Part 4 | >Part 5 | Part 6 | Part 7

Part 5: Automating Testing and Code Coverage

Automatically running tests before commits with ghooks

I really think git hooks are pretty sweet! So git has events right? commit, push, receive etc. Well what if you wanted to do stuff before you committed or after a push? Well ghooks is how you do that. 

glyphicons-28-search read more at  git-scm.com , http://githooks.com/ or on npm

Let’s get started by installing it as a dev dependency for this project. You don’t want to install it globally btw as it can cause problems.  Head to your console and type:

$ npm i -D ghooks

Now we need to configure ghooks to run our test before every commit. This is pretty easy. Go to package.json and add:

glyphicons-424-git-create
"config": {
        "ghooks": {
                "pre-commit": "npm run test:single"
        }
}

Now head into your test file and break the test by making it fail, then run:

$ git commit -am "Testing ghooks"

It should have prevented the commit, so go back and fix the test. Then let’s see it work on when we run our commit script.

$ git status
$ git diff
$ git add .
$ git status
$ npm run commit

Great! Now that we have automated the testing process a bit how about taking a look at how much of our code is covered by our tests? How would we do this? There are several ways but I am most comfortable with Istanbul, it has great docs and is pretty widely used.

Adding code coverage with Istanbul

Install  istanbul as a dev dependency:

$ npm i -D istanbul

Verify in package.json that istanbul was added to the devDependencies section. Now we need to adjust the test scripts. Change test:single to:

glyphicons-424-git-create
“test:single”: “istanbul cover -x *.test.js _mocha -- -R spec src/index.test.js”

What is happening there? Well first we are firing off the istanbul binary and passing in cover. This passes in the cover command and saves coverage.json and reports after execution. Next we see -x to ignore checking the coverage ON our test files since we are not writing tests for tests. The _mocha tells istanbul that the next flags passed in should go to mocha and not to istanbul. Now run our test and see the difference now:

$ npm run test:single

Pretty neat eh! Let’s make it even cooler.

Adding Code Coverage Checking

open package.json and set new ghooks to:

glyphicons-424-git-create
"config": {
    "ghooks": {
      "pre-commit": "npm run cover && npm run check-coverage"
    }

Go back up to scripts in package.json and add:

“check-coverage”: “istanbul check-coverage --statements 100 --branches 100 --functions 100 --lines 100”

The –name value above set’s what percentage we want our code to pass before we let it go forward. Since this is a small project 100 is a good bet. To see what this does run:

$ npm run check-coverage

Now add a new function to your index.js and run tests again. I simply created  a dummy function:

function notCovered() {
     return 'oops';
}
$ npm run test: single

This will let us check the coverage of that specific test allowing us to re-run check-coverage:

$ npm run check-coverage

Now since we are all about the automation we want to add this to Travis so open .travis.yml and add to script: section

glyphicons-424-git-create 
- npm run check-coverage

Sweet! Now remove that bunk function before we forget. Now we are going to add codecove.io report viewing to the project. I mean why not right?

Go to codecov.io and sign up for an account. Integrate your repo for the npm module. The steps are pretty straight forward. Now go to the terminal and from within the project directory run:

$ npm i -D codecov.io

Then go to package.json we will pipe a report into the codecov binary by adding a new script to package.json:

“report-coverage”: “cat ./coverage/lcov.info | codecov”

Now on to .travis.yml (this pattern is getting familiar right?)

after_success:

- npm run test report-coverage

 

$ git status
$ git add .
$ npm run commit
$ git push

Check code coverage at codecov.io. Optionally you can add a chrome extension for codecov here to see more integration on github.com.

Now wasn’t that easy!

Adding badges to the Readme

Head to http://shields.io and search for Travis copy url into README.md then edit the url to be your repo. You can also look at the styles at the bottom if you want to tweak the shield. Do the same for:

  • codecov
  • npm version
  • npm downloads
  • npm license
$ git status
$ git add .
$ npm run commit
$ git push

Next… ES6 support!

Key:

glyphicons-55-clock  = Time Saving Idea

glyphicons-499-sunglasses = Pro Tip

glyphicons-31-pencil = Note

glyphicons-197-exclamation-sign = Alert

glyphicons-424-git-create = Code Update

glyphicons-28-search  = A Closer Look

Publishing an NPM Module Part 3

These are my notes based on the phenomenal tutorial by Kent C. Dodds hosted by egghead.io both of which are my go to sources when I want to learn something new. I highly suggest you sign up for the pro subscription.

Part 1 | Part 2 | >Part 3 | Part 4 | Part 5 | Part 6 | Part 7

Part 3: Setting up Unit Testing

There are tons of testing libraries out there. I am going to stick with the more common ones mocha and chai for now. In later parts I will introduce a few more. In order to use them we should install them!

Head to your trusty console:

$ npm i -D mocha chai

glyphicons-499-sunglasses  the above is the same as ‘npm install mocha chai –save-dev’ only faster!

Create index-test.js in the same directory.

$ touch src/index.test.js

Now looking at our index.js we see we have a few things to test. At least 4 since we do have 4 methods.

module.exports = {
    list: list,
    single: single,
    startsWithLetter: startsWithLetter,
    numberOfNames: numberOfNames
}

Let’s start building our index.test.js. We will first wrap our initial section in a describe block. This is just a container to describe what we should expect to see tested inside.

var expect = require('chai').expect;
var rng = require('./index');

describe('Our first tests', function () {
   
});

Our list method should return an array containing strings. So let’s test for that!

describe('tests should be running', function () {
    describe('list()', function () {
        it('Expect it to return an array of strings', function () {
            expect(rng.list()).to.satisfy(isArrayOfStrings);

            function isArrayOfStrings(array) {
                return array.every(function(item){
                    return typeof item === 'string';
                })
            }
        });
    });
});

glyphicons-28-search Let’s take a closer look at each part in the above test. We have another describe block, this time focused on the all method. This is a nice way of grouping our tests to keep them focused. The first argument in describe is a string denoting the topic, the second is a function that will contain our actual tests and also could be used to set up mock data if we needed it.

The it is similar to describe in that you first give it a string but this time it will be much more specific. This is what you are actually testing. In this example we want to make sure that the all function returns an array of strings. The second argument is again a function block where we will do the specific test.

One of the benefits of this style of testing is to create very readable tests. Even if you don’t know the nitty gritty you could read the test and it will explain itself. Using expect or should gives you a clear idea of what we are looking for. They are pretty similar, however there are some syntactical differences to be aware of. (read more)

These allow you to chain together natural language assertions. Expect takes the value you want to test and then you chain together what assertions you need to use in order to test. The language used to chain the expect and the test generally do not  provide testing functionality.

List of Chains:

    .to
    .be
    .been
    .is
    .that
    .which
    .and
    .has
    .have
    .with
    .at
    .of
    .same

These get chained together finally ending in an actual test assertion. For example in my test we see:

expect(rng.list()).to.satisfy(isArrayOfStrings);

This means that we expect that when we execute rng.list() that it will satisfy the given truth test. Here our truth test is another function that checks to see if every item in the array has a type of string.  This is very flexible and will help you easily generate tests. The full api can be read here. Here are some of the ones I use most:

.match(regexp)

  • @param { RegExp } RegularExpression
  • @param { String } message _optional_

Asserts that the target matches a regular expression.

expect('foobar').to.match(/^foo/);

.instanceof(constructor)

  • @param { Constructor } constructor
  • @param { String } message _optional_

Asserts that the target is an instance of constructor.

var Tea = function (name) { this.name = name; }
  , Chai = new Tea('chai');

expect(Chai).to.be.an.instanceof(Tea);
expect([ 1, 2, 3 ]).to.be.instanceof(Array);

.equal(value)

  • @param { Mixed } value
  • @param { String } message _optional_

Asserts that the target is strictly equal (===) to value. Alternately, if the deep flag is set, asserts that the target is deeply equal to value.

expect('hello').to.equal('hello');
expect(42).to.equal(42);
expect(1).to.not.equal(true);
expect({ foo: 'bar' }).to.not.equal({ foo: 'bar' });
expect({ foo: 'bar' }).to.deep.equal({ foo: 'bar' });
Now that you are familiar with the basics of testing write a few more tests for your functions. Here is an example of basic testing covereage:
var expect = require('chai').expect;
var randomNameGenerator = require('./index');


describe('tests should be running', function () {
    describe('list()', function () {
        it('should be an array of strings', function () {
            expect(randomNameGenerator.list()).to.satisfy(isArrayOfStrings);

            function isArrayOfStrings(array) {
                return array.every(function(item){
                    return typeof item === 'string';
                })
            }
        });

        it('should contain `FirstName MiddleName LastName`', function () {
            expect(randomNameGenerator.list()).to.include('FirstName MiddleName LastName');
        });
    });

    describe('single()', function () {
        it('should be a string', function () {
            expect(randomNameGenerator.single()).to.be.a('string');
        });

        it('should contain three names', function () {
            var arrayOfName = randomNameGenerator.single().split(' ');
            expect(arrayOfName).to.have.lengthOf(3);
        });
    });

    describe('startsWithLetter()', function () {
        it('should be a string', function () {
            expect(randomNameGenerator.startsWithLetter('A', 'C', 'E')).to.be.a('string');
        });

        it('should contain three names', function () {
            var arrayOfName = randomNameGenerator.startsWithLetter('A', 'C', 'E').split(' ');
            expect(arrayOfName).to.have.lengthOf(3);
        });

        it('should start with the passed values for f,m,l of A, C, E', function () {
            var arrayOfName = randomNameGenerator.startsWithLetter('A', 'C', 'E').split(' ');
            expect(arrayOfName[0][0]).to.equal('A');
            expect(arrayOfName[1][0]).to.equal('C');
            expect(arrayOfName[2][0]).to.equal('E');
        })
    });

    describe('numberOfNames()', function () {
        it('numberOfNames(3) should have a length of three', function () {
            var arrayOfNames =  randomNameGenerator.numberOfNames(3);
            expect(arrayOfNames).to.have.lengthOf(3);

        });

        it('numberOfNames() should default to one', function () {
            var arrayOfOneName = randomNameGenerator.numberOfNames();
            expect(arrayOfOneName).to.have.lengthOf(1);
        });
    });

});

Now that we have some basic tests we will create a script to run them. Open package.json and in the scripts section we will change the test to:

"test": "mocha src/index.test.js -w"

The -w watches the file system for changes and re-runs the test. There are many more options head to mochajs.org and search for usage:

There we go, we have set up a basic testing framework!

Next… Automating releases

Key:

glyphicons-55-clock  = Time Saving Idea

glyphicons-499-sunglasses = Pro Tip

glyphicons-31-pencil = Note

glyphicons-197-exclamation-sign = Alert

glyphicons-424-git-create = Code Update

glyphicons-28-search  = A Closer Look

Publishing an NPM Module Part 2

These are my notes based on the phenomenal tutorial by Kent C. Dodds hosted by egghead.io both of which are my go to sources when I want to learn something new. I highly suggest you sign up for the pro subscription.

Part 1 | >Part 2 | Part 3 | Part 4 | Part 5 | Part 6 | Part 7

Part 2: Creating the library

If you missed it check out Part 1: The Setup

This is going to be a tough section. I will be using my module as an example but you will need to create your own. I was inspired by the original tutorial on egghead.io that I can’t recommend enough! Kent C. Dodds is absolutely fantastic. I have a cousin who is an author and one of her issues was coming up with names so I created my random-character-name module to help her out.

The initial step is the same, at the console inside your projects directory type:

$ touch src/index.js

For mine I am also going to use another library in mine called unique-random-array. I also created a data directory to hold my first, middle and last name json objects.

$ npm i -S unique-random-array

glyphicons-499-sunglasses  npm i -S is equivalent to npm install –save

Here is the inital code for my project.

var uniqueRandomArray = require('unique-random-array');
var _ = require('lodash');

//define available data
var firstNames = require('../data/first-names.json');
var middleNames = ('../data/middle-names.json');
var lastNames = ('../data/last-names.json';

//random generators
var randomFirstName = uniqueRandomArray(firstNames);
var randomMiddleName = uniqueRandomArray(middleNames);
var randomLastName = uniqueRandomArray(lastNames);

//filter functions
var filteredNames = function (nameList, initial) {
    return nameList.filter(function (name) {
        return name[0] === initial;
    })
};

module.exports = {
    list: list,
    single: single,
    numberOfNames: numberOfNames
}

//available methods
function list() {
    var allNames = ["FirstName MiddleName LastName"];
    for (var i = 0; i < firstNames.length; i++) {
        var tmpName = randomFirstName() + ' ' + randomMiddleName() + ' ' + randomLastName();
        allNames.push(tmpName);
    }
    return allNames;
}

function single() {
    return randomFirstName() + ' ' + randomMiddleName() + ' ' + randomLastName();

}

function numberOfNames(number) {
    if (number === undefined) {
        number = 1;
    }
    var allNames = [];
    for (var i = 0; i < number; i++) {
        //Math.floor((Math.random() * 10) + 1);
        var tmpName = randomFirstName() + ' ' + randomMiddleName() + ' ' + randomLastName();
        allNames.push(tmpName);
    }
    return allNames;
}

Now, just because we have a thing lets commit that thing!

git commit -am “Initial Commit”

Publish to NPM

Now is the exciting part! We will publish to NPM! Head to your friendly console and type:

$ npm publish
$ npm info the-name-of-your-repo

Let’s do a quick test, we will jump to your Desktop and try it out!

$ cd ~/Desktop
$ mkdir npmtest
$ npm init -y
$ npm install the-name-of-your-package

Now anyone with npm installed can install your package! I was giddy the first time this hit me. Since we really have something now so let’s set our version to 1.0.0 on github.

$ git tag 1.0.0
$ git push --tags

glyphicons-28-search   This a great read if you want to take a closer look.

Head to your https://github.com/repo/releases and you will see the version 1.0.0 tag. Also head to https://www.npmjs.com/package/the-name-of-your-package to check it out! You are a contributor now! (send me a link and I will star you)

Releasing a new version

Add a new feature to index.js. Here is an example. We have added a new function to return a name with specific initials.

function startsWithLetter(f, m, l) { 
    var firstName = _.sample(filteredNames(firstNames, f)); 
    var middleName = _.sample(filteredNames(middleNames, m));
    var lastName = _.sample(filteredNames(lastNames, l));
    return firstName + ' ' + middleName + ' ' + lastName; 
}

We also want to make sure we export our new function.

glyphicons-424-git-create
module.exports = {
    list: list,
    single: single,
    startsWithLetter: startsWithLetter,
    numberOfNames: numberOfNames
}

Since this is not a breaking change and is not just a bug fix we will change the middle number.

glyphicons-28-search  Read about semver at http://semver.org/ but a quick rundown is as follows:

major(breaking).minor(non-breaking new feature).patch(bug)

$ git status
$ git diff
$ git add -A
$ git status
$ git commit -m "[feat] add startsWithLetter method."
$ git tag 1.1.0 //set new version
$ git push
$ git push --tags
$ npm publish
$ npm info the-name-of-your-package

Pushing Beta Version

Make a change. Something you are not sure you want in the default download.  I just added a bunch of comments, nothing serious. 

$ git diff
$ git add -A
$ git commit -am "[docs] add verbose documentation in comments"
$ git tag 1.2.0-beta.0
$ get push
$ git push --tags
$ npm publish --tag beta

To install beta

$ npm i the-name-of-your-package@beta

Or a specific version:

$ npm i the-name-of-your-package@1.2.0-beta.0

Next… Setting Up Testing

Key:

glyphicons-55-clock  = Time Saving Idea

glyphicons-499-sunglasses = Pro Tip

glyphicons-31-pencil = Note

glyphicons-197-exclamation-sign = Alert

glyphicons-424-git-create = Code Update

glyphicons-28-search  = A Closer Look

My first NPM Module

I finally got around to publishing an NPM module (Thank you Kent C Dodds!) It is pretty simple, but it  solves a problem I have had as a writer. Names! It let’s a user generate a name, an array of names with a given length, a massive list of names or a name with specific Initials.

Simply run the following.

npm i random-character-name

and you are good to go! Head to npm or github if you want to contribute!

The method list() will return a list of all random names that were generated. The method single() will return a single random name. The method startsWithLetter(f,m,l) will let you set the initials. The method numberOfNames(number) will return the requested number of names.

var rndNameGen = require(random-character-name);
 
rndNameGen.list();
//generates a large array of names 
/* 
ex.
  [‘Em Andre Vento’,
  ‘Marsiella Lester Drisko’,
  ‘Lou Charley Hoang’,
  ‘Bettye Ransell Cristabel’,
  …
  ‘Shawnee Timothee Rigby’,
  ‘Roch Wilbur Ithnan’,
  ‘Shanta Wheeler Milicent’,
  ‘Janela Wally Marlowe’ ]
 
*/
 
rndNameGen.single(); 
//generates a string with a random name 
//ex. ‘Donnie Reinhard Levin’ 
 
rndNameGen.startsWithLetter(A,C,E);
//generates a string with a name with requested initials 
//ex. ‘Ajay Christophorus Elset’ 
 
rndNameGen.numberOfNames(3)
//generates an array with the number of names requested. 
/*
ex.
[ ‘Nedi Burt Lexine’,
  ‘Cairistiona Jacobo Merl’,
  ‘Annaliese Bartolomeo Cherian’ ]
*/

Sem.Ver.Blog

It is just Numbers and Dots, right?

I just released a new version of software. I called it 1.0.0. Why did I do that? Really it was because that is just what I do. When I make a very tiny change I adjust the last number up. When I have enough tiny changes that I can bundle them up I adjust the middle number and when I have a significant number of those changes I adjust the first number.

Is this right? No, no it is not. So it’s time to figure this out. Let me go to the source:

(from http://semver.org/)

Summary

Given a version number MAJOR.MINOR.PATCH, increment the:

  1. MAJOR version when you make incompatible API changes,
  2. MINOR version when you add functionality in a backwards-compatible manner, and
  3. PATCH version when you make backwards-compatible bug fixes.

Additional labels for pre-release and build metadata are available as extensions to the MAJOR.MINOR.PATCH format.

This makes way more sense. When you make incompatible API changes the major version must change, otherwise it is just extending the current versions functionality (still backwards-compatible) and finally if you are making changes, that don’t add functionality but fix originally intended functionality while maintaining the same backwards-compatibility it is a patch.

Why should I care? Do you want to live in dependency hell? I thought not. The more complicated software gets, the more likely conflicts occur among dependencies and interdependencies.  How do we avoid this? By making sure that when we write a library with a public API we show how it’s used and how it will not be used. Once these restrictions change we know we have to think about bumping up the major version. Those who want to keep their code working can stick with the working major version until they have reviewed potential impact and decide to upgrade or not.

It is not overly complicated, but I highly suggest reading the full spec to become fully enlightened. versioning

 

Prototypal Inheritance and you.

Let’s first start by saying that Javascript is a little interesting when it comes to classes and objects. Technically I think Javascript is basically classless (probably why I like it so much…) but there are class-like activities. Just remember at its root, an Object is a just a unordered collection of key:value pairs. Anything other than strings, numbers, booleans, undefined and null is an object.

Let’s create some objects.

var anObject = {};
anotherObject = new Object();

-or-

function MyObject() {}
var myObject = new MyObject();

 

Now where does Prototypal Inheritance enter into this? Each object has an internal link to another object, known as its prototype.  This other object also has a prototype, and so on until we reach null as its prototype.null ending the chain.

Objects are buckets of properties with links to a prototype object. When access to a property is requested it will look not only at the specific objects property but all the way back up the prototype chain until the property is found or the end of the chain.

Let’s add some methods to the objects.

function MyObject() {}

var myObject = new MyObject();

MyObject.simpleLog = function(value) {
    console.log(value);
}

var difObject = new MyObject();

difObject.simpleLog = function(value){
    console.log('The value is: ', value);
}

difObject.simpleLog("something should go here"); //calls the instance specific method
MyObject.simpleLog("something should go here"); //calls the static Object method
MyObject.prototype.simpleLog = MyObject.simpleLog; //apply the static method to all instances from here on in
difObject.simpleLog("still calling instance method");  //still calls the instance method
var yetAnotherObject = new MyObject();
yetAnotherObject.simpleLog("inherited from MyObject"); //inherited simpleLog() from MyObject
MyObject.simpleLog("I also inherit."); //pre-existing instances also inherit the new function

 

So as you can see when you add a method to the prototype it gets inherited along the prototype chain. There is an order to when this gets used as you can see in the difObject.simpleLog(); call that it uses the local instance method as it does not have to go up the chain to find the one we added with the line MyObject.prototype.simpleLog = MyObject.simpleLog;

Now when we reference methods in JavaScript it is not strictly accurate in the form that other class-based languages. For JavaScript any function that you add as an object property becomes a method for that object.  An inherited function acts just as any other property on that object, including method overriding!

Another key point to remember is what happens to this. Its value points to the inheriting object not back to the prototype object where the function is an own property. Let’s look at another example.

var myObject = {
    staticValue: 40,
    someMethod: function(val) {
      console.log(this.staticValue);
      return this.staticValue + 1;
    }
};

console.log(myObject.someMethod()); //42

var yourObject = Object.create(myObject);

yourObject.staticValue = 20;

console.log(yourObject.someMethod());  //21

 

As you can see once we overwrite a value it will no longer work its way up the chain allowing for differences in the objects after they are created. Very useful! I will be digging deeper into objects and modules in another post.

YDKJS Types & Grammar

Chapter 2 “Values”

Javascript has some interesting aspects to arrays, strings and numbers! In this chapter we explore them in a little more detail.

Arrays

Javascript arrays are not type-enforced. They can contain strings, numbers, objects, even other arrays aka multi-dimensional array.

var myArray = [ 1, "1", {1:"One"}, ["Juan"] ];

 

Arrays also do not need to have their size predefined. You can just declare and add willy nilly. There is some care when using delete on an array because it will remove the slot, but even if that slot is the last element it does not update the length property of that array. Also watch out for “sparse” arrays by creating empty or missing slots. This can lead to some unintended consequences when dealing with the array values.

Another odd thing is that since arrays are also objects you can have string key/property values added to them, but this does not change the value of the length of that array, unless that value can be coerced into a base-10 number!

var myArray = [ ];
myArray[0] = 1;
myArray["crazytown"] = 42;

myArray.length == 1; //true
myArray["crazytown"] == 42; //true
myArray.crazytown; //42

//watch out for numbers!

var myOtherArray = [ ];
myOtherArray["42"] = "crazytown";
myOtherArray.length == 43; //true 

 

Interesting ES6 built-in called Array.from(…) It can do more that I will have to learn about!

var arr = Array.from( arguments );

 

Strings

At first glance one might think that strings are just arrays of characters. Strings have a length property, an indexOf method and even a concat method. So they are the same right? Not so fast! JavaScript strings are immutable, while arrays are! Look at the following:

myString = "ramen";
myArray = [ "r", "a", "m", "e", "n" ];

myString.length == myArray.length; //true

myString.indexOf( "e" ) == myArray.indexOf("e"); //true

//however watch this

myString[1] = "X";
myArray[1] = "X";

myString; // "ramen"
myArray; // myArray = [ "r", "X", "m", "e", "n" ];

 

If you find yourself treating strings as arrays, consider using just an array. You can always join the array back up if you need to use it as a string.

Numbers

Unlike many other programming languages javascript has only one flavor of numeric datatype. number. This number contains integer(ish) numbers and fractional decimal numbers. The ish above is because the integers are just not exactly as you would expect. Google has a ton of examples, here is one. Trailing and leading 0’s are removed from decimals 0.42 becomes .42 and 4.200 becomes 4.2 etc.

Another interesting thing is that numbers get access to the Number.prototype methods, like toPrecision() and and toString(). Some caveats when using them. If you tried 42.toString() returns invalid because the initial . is considered to be a part of the 42, you can get around this by using parentheses (42).toString() or 42..toString(). Things have changed a bit for octal literals in ES6 and/or strict mode so that 0363 no longer equates to 243 instead you would use 0o363… very fun.

You can also get whonky stuff like 0.1 + 0.2 === 0.3 returning false… There are ways around this, ES6 has some specific tools for this (see Number.EPSILON). ES6 also has Number.MAX_SAFE_INTEGER (9007199254740991) and Number.MIN_SAFE_INTEGER (-9007199254740991) it also has an isInteger test that you can polyfill by checking typeof num is “number” and its % 1 is 0. It gets deeper with ES6 as you can use .isSafeInteger

Numbers are strange, mmmkay.

Special Values

I like these. They are special! They are null, undefined, and void . null being an empty value and undefined being a missing value. null is a keyword making it have a sort of protection field around it so you can assign null to something. undefined can be, at least in non-strict mode, you can do bad things like setting undefined to equal something! Just don’t do it!

Void is an interesting one, I have dug around and I don’t think I know why I would use this. I am sure as I get deeper into javascript I will figure it out.

Special Numbers

NaN, not a number… even though the typeof for a NaN is a number… mmm bad naming conventions. I have learned to think of it as just being a bad number. It happens when you try a mathematical expression using something that is not a number. Another interesting quirk about NaN is that it is not equal to itself! so NaN !== NaN… kooky. Using this we can create an interesting polyfill to check to see if something is NaN.

if (!Number.isNaN) { //if the browser does not have access to this
    Number.isNaN = function (n) {
        return n !== n;
    }

 

Cool! I will have to make sure I start putting this in!

To Infinities and beyond! Okay not beyond, but right to them! Basically this means you can make a value that is just too big (or too small) for JS to deal with and it assigns it Infinity or -Infinity. This leads us to another special case in javascript…

Zero or 0 or -0?

Javascript has both a 0 and a -0. What makes it even more difficult is that 0 == -0. Another helper function pops up!

function isNegZero(n) {
    n = Number( n );
    return (n === 0) && (1 / n === -Infinity);
}

 

Again I think I need to get deeper into code to see why this would matter. For now I will just keep it in the back of my mind.

Special Equality

When we need to check for these special equalities ES6 gives us a tool to help. Object.is() to the rescue. So now Object.is( 0, -0); returns false! Wahoo! Save Object.is for special occasions where you might need to check this!

Value vs. Reference

A reference in javascript points to a space in memory so if you have multiple references to this space in memory they do not reference each other. Only the type of the value designates whether the value is assigned by copy or by reference.

Scalar Primitives are always assigned by copy: null, undefined, string, number, boolean and symbol.

Compound values such as objects and functions always create a reference copy on assignment or when passed.