Friday, 20 May 2016

Functional static functions are okay!

Programming Rule #1

Static functions are fine if they are functional

If a static function returns same output for same input and doesn’t mutate global variables/states then it is functional and thus this behavior is okay.

Key points

Function needs to be static

Function needs to return value

Function should not mutate variables

Function might accept input.

There is a strong correlation between input and output.

Reference

Viewership Updates - May 20, 2016

Today

enter image description here

Past Week

enter image description here


Past month

enter image description here

All time

enter image description here

enter image description here

enter image description here

Monday, 16 May 2016

GitHub UI Hack for better reviewing experience.

Hack that hides notes while reviewing code on GitHub

After clicking three show notes button/checkbox, I got bored and tired. Thus here’s a small snippet that takes care of such checkboxes at once.

I tested only on safari. I am lazy.

Lazy hack

[].forEach.call(document.getElementsByClassName('js-toggle-file-notes'), function (x) { if(x.checked) x.click(); });

A bit better and readable code:

Readable hack

var toggleButtons = document.getElementsByClassName('js-toggle-file-notes');

function uncheck(x) {
    if(x.checked) {
        c.click();
    }
}

[].forEach.call(toggleButtons, uncheck);

Did I say hack?

Note: I think click is coming from jQuery.

I might be wrong as much as I might be right. I do not have time right now to explore that. I have a code review of 37 files to attend.

Yeah. A 37 file change PR! With 1000+ changes and 100+ conversation bits.

Fetching all the headings from page of an online book.

const link = 'http://exploringjs.com/es6/ch_classes.html';

let [h1, h2, h3, h4, h5, h6] = [ 
    document.getElementsByTagName('h1'),
    document.getElementsByTagName('h2'),
    document.getElementsByTagName('h3'),
    document.getElementsByTagName('h4'),
    document.getElementsByTagName('h5'),
    document.getElementsByTagName('h6') 
  ];

let printAllHeadingsViaNodeElement = function (node) {
  for(var i = 0; i < node.length; i++){
    console.log(node[i].textContent);
  }
};

printAllHeadingsViaNodeElement(h1)

printAllHeadingsViaNodeElement(h2)
15. Classes

printAllHeadingsViaNodeElement(h3)
15.1 Overview
15.2 The essentials
15.3 Private data for classes
15.4 Simple mixins
15.5 The details of classes
15.6 The details of subclassing
Methods are a special kind of function now
15.7 The species pattern
15.8 The pros and cons of classes
traits.js: traits library for JavaScript
15.9 FAQ: classes
15.10 What is next for classes?
15.11 Further reading

printAllHeadingsViaNodeElement(h4)
15.2.1 Base classes
15.2.2 Inside the body of a class definition
15.2.3 Subclassing
15.3.1 Private data via constructor environments
15.3.2 Private data via a naming convention
15.3.3 Private data via WeakMaps
15.3.4 Private data via symbols
15.3.5 Further reading
15.5.1 Various checks
15.5.2 Attributes of properties
15.5.3 Classes have inner names
15.6.1 Prototype chains
15.6.2 Allocating and initializing instances
15.6.3 Why can’t you subclass built-in constructors in ES5?
15.6.4 Referring to superproperties in methods
15.7.1 Helper methods for examples
15.7.2 The standard species pattern
15.7.3 The species pattern for Arrays
15.7.4 The species pattern in static methods
15.7.5 Overriding the default species in subclasses
15.8.1 Complaint: ES6 classes obscure the true nature of JavaScript inheritance
15.8.2 Complaint: Classes provide only single inheritance
15.8.3 Complaint: Classes lock you in, due to mandatory new

15.9.1 Why can’t classes be function-called?
15.9.2 How do I instantiate a class, given an Array of arguments?

printAllHeadingsViaNodeElement(h5)
15.2.1.1 No separators between members of class definitions
15.2.1.2 Class declarations are not hoisted
15.2.1.3 Class expressions
15.2.2.1 constructor, static methods, prototype methods
15.2.2.2 Static data properties
15.2.2.3 Getters and setters
15.2.2.4 Computed method names
15.2.2.5 Generator methods
15.2.3.1 The prototype of a subclass is the superclass
15.2.3.2 Superconstructor calls
15.2.3.3 Overriding the result of a constructor
15.2.3.4 Default constructors for classes
15.2.3.5 Subclassing built-in constructors
15.5.3.1 The inner names of named function expressions
15.5.3.2 The inner names of classes
15.6.1.1 Left column: classes (functions)
15.6.1.2 Right column: the prototype chain of the instance
15.6.2.1 Safety checks
15.6.2.2 The extends clause
15.6.3.1 The solution: ES6 subclassing
15.6.4.1 Where can you use super?
15.6.4.2 Pitfall: A method that uses super can’t be moved
15.7.5.1 Setting the species to a constructor of your choosing
15.7.5.2 Setting the species to null

printAllHeadingsViaNodeElement(h6)
15.7.5.1.1 Specifying the species via a data property

A lot of text replacing.

Sample git aliases - May 2016

Alias

console on GNU/Linux and MAC have ability to alias the commands via ~/.bash_profile, ~/.bash_aliases or ~/.profile etc.

Note: I am not sure about Windows.

I am not too big on GUI tools for git. At most, I love gitk and git extensions; which work for linux and windows. Unfortunately, mac git-guis are rather useless. (That’s solely what I have found. Didn’t ask anyone, if you know, please teach me a lesson or I shall taunt you one more time.)

Here’s my ~/.profile file that contains git aliases.

Sample


alias gs="git status"

alias gd="git diff"

alias gl="git log"
alias gln3="git log -n3"

alias gpr="git pull --rebase"
alias gprud="git pull --rebase upstream develop"
alias gprum="git pull --rebase upstream master"

alias gpo="git push origin"
alias gpom="git push origin master"
alias gpod="git push origin develop"

alias gpfom="git push -f origin master"
alias gpfod="git push -f origin develop"

alias gpu="git push upstream"
alias gpo="git push origin"

alias gf="git fetch"

alias gco="git checkout"
alias gcom="git checkout master"
alias gcod="git checkout develop"

alias grv="git remote -v"

alias conflicted-files="git diff --name-only --diff-filter=U"
alias whats-staged="git diff --cached"

alias visualize-tree="git log --pretty=oneline --graph --decorate --all"
alias all-thats-ignored="git ls-files --others -i --exclude-standard"

Breakdown

check check

git status and git diff are the commands I use almost 100+ times a day. I have aliased them as gs and gd.

On linux, there’s a tool called GS, doing this prevents that tool from running from console. You have been warned.

get

Next up is git pull --rebase. Here’s the rub, a lot of developers don’t understand difference between git pull and git pull --rebase. I just face my palm when working with them. I give you gpr.

Now, with gpr you need to specify remote and branch if not dealing with origin/master. git pull --rebase upstream master is too much to type. So, gprum.

You can see that gprud is not far from here.

give

We have to push our changes.

git push origin master becomes gpom.
git push origin develop becomes gpod.

But there are more branches to push to origin. I had to refactor.

git push origin becomes gpo.

so pushing to my-feature branch becomes as easy as: gpo my-feature.

change

Well, if you want to change your branch all you have to do is gco. It is an alias for git checkout.

You frequent develop branch => gcod.
You visit master alot => gcom.
general refactor: gco

Also easy to create a new branch and switch to it

$> gco -b new-feature-branch

Rest is pretty much self explanatory.

Fin

Sample Gruntfile - May 2016

Gruntfile.js is still an JS file.

Note: In English, if you are using abbr. then you use article an instead of a before it.

Realization

I had a realization today that a Gruntfile is still ecmascript file.

Action

So I refactored my Gruntfile.js file.

Output / Code

Note: Time taken is half an hour.


'use strict';

module.exports = function (grunt) {
    const fromGruntTaskDirectory = 'grunt-tasks';
    const preBuildLint = [ 'eslint' ];
    const build = [ 'dustjs', 'less', 'webpack', 'copyto' ];
    const rebuild = [ 'clean', 'build' ];

    const testing = (() => {
        function TestScopes() {
            this.client = (() => {
                return {
                    unit: [ 'karma' ],
                    integration: [ 'protractor' ]
                };
            })();
            this.server = (() => {
                return {
                    unit: [ 'mochacli:unit', 'codecoverage:unit', 'checkcoverage:unit' ],
                    integration: [
                        'mochacli:serverintegration'
                    ]
                };
            })();
            this.unit = this.client.unit.concat(this.server.unit);
            this.integration = this.client.integration.concat(this.server.integration);
            this.everything = this.unit.concat(this.integration);
        }
        return new TestScopes();
    })();

    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json')
    });

    grunt.loadTasks(fromGruntTaskDirectory);

    grunt.registerTask('client:unit', testing.client.unit);
    grunt.registerTask('server:unit', testing.server.unit);

    grunt.registerTask('server:integration', testing.server.integration);

    grunt.registerTask('client:integration', testing.client.integration);

    grunt.registerTask('lint', preBuildLint);
    grunt.registerTask('build', preBuildLint.concat(build));

    grunt.registerTask('unit', testing.unit);
    grunt.registerTask('integration', testing.integration);

    grunt.registerTask('default', rebuild.concat(testing.everything));
};

I know that this is not cleanest possible code. But hey if I showed you the original one, …

Advantages

This code has following advantages:

  1. It doesn’t have strings and arrays of strings thrown randomly.
  2. Better structure.
  3. A little more object oriented; though it could have been better.

Drawbacks

  1. This is May, 2016 - Why is not it in ES 2015 at least?
  2. Is it really that clean?
  3. Why are the variables inside modules.export ?
  4. I don’t understand some of it.

Rationalization

Notice how I have used rationalization instead of rationale; because I have none.

  1. I am learning ES 6 and NodeJS. Since I am new to JS, it takes time to learn fundamentals and advanced concepts. I’d say my fundamentals are better than okay; i.e. more towards North on North-pointing compass.
  2. I still don’t fully understand how NodeJS application is pieced together.
  3. This Gruntfile is output of 12 people working on the project. I am good with Jasmine; but server side and browser testing still eludes me.

Final Thoughts

I can do better. I am learning ES 2016 and soon will be able to think in the language.

Update

#1 - Taking building blocks out.


'use strict';

const fromGruntTaskDirectory = 'grunt-tasks';
const preBuildLint = [ 'eslint' ];
const build = [
    'dustjs',
    'less',
    'webpack',
    'copyto'
];
const rebuild = [ 
    'clean',
    'build'
];

const testing = (() => {
    function TestScopes() {
        this.client = (() => {
            return {
                unit: [ 'karma' ],
                integration: [ 'protractor' ]
            };
        })();
        this.server = (() => {
            return {
                unit: [ 'mochacli:unit', 'codecoverage:unit', 'checkcoverage:unit' ],
                integration: [
                    'mochacli:serverintegration'
                ]
            };
        })();
        this.unit = this.client.unit.concat(this.server.unit);
        this.integration = this.client.integration.concat(this.server.integration);
        this.everything = this.unit.concat(this.integration);
    }
    return new TestScopes();
})();

module.exports = function (grunt) {
    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json')
    });

    grunt.loadTasks(fromGruntTaskDirectory);

    grunt.registerTask('client:unit', testing.client.unit);
    grunt.registerTask('server:unit', testing.server.unit);

    grunt.registerTask('server:integration', testing.server.integration);

    grunt.registerTask('client:integration', testing.client.integration);

    grunt.registerTask('lint', preBuildLint);
    grunt.registerTask('build', preBuildLint.concat(build));

    grunt.registerTask('unit', testing.unit);
    grunt.registerTask('integration', testing.integration);

    grunt.registerTask('default', rebuild.concat(testing.everything));
};

#2 - Moving to ES 2015 classes.


const ClientScope = class {
    unit() { return  [ 'karma' ]; }
    integration() { return [ 'protractor' ]; }
};
const ServerScope = class {
    unit() { 
        return [ 
            'mochacli:unit',
            'codecoverage:unit',
            'checkcoverage:unit'
        ];
    }
    integration() {
        return [
            'mochacli:serverintegration'
        ];
    }
};

const testing = (() => {
    function TestScopes() {
        this.client = new ClientScope();
        this.server = new ServerScope();
        this.unit = this.client.unit().concat(this.server.unit());
        this.integration = this.client.integration().concat(this.server.integration());
        this.everything = this.unit.concat(this.integration);
    }
    return new TestScopes();
})();

#3 - A bit more classey.

soon.