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.

 

addEventListener() and you!

Event Delegation

What is it? Well I can tell you it is great! Gone are the days of an onMouseOver event watcher on every list item or span on your page. Now you can tell the parents to pay attention to their kids by reminding them to listen to the conversations they little ones are having and reacting appropriately. We do this by using  addEventListener. This brilliant function does just what it says. This one is easier to explain by example, so here goes.

<div id="parent-div">
<span id="child-1">One</span>
<span id="child-2">Two</span>
<span id="child-3">Three</span>
</div>

<script>
// Get the element, add a click listener...
document.getElementById("parent-div").addEventListener("mouseover", function(e) {
// e.target is the moused over element!
// If it was a span item
if(e.target && e.target.nodeName == "SPAN") {
// SPAN item found! Output the ID!
console.log("List item ", e.target.id.replace("child-", ""), " was evented!", e);
}
});
</script>

It is really as simple as that. Now when any child span is moused over the id number for that child will be sent to the console. You can also use specific classes if you use .matches(“className”). Digging deeper into this has me going down the MouseEvent rabbit hole so I know what my next post will be about! I mean who wouldn’t want to learn about MouseEvent.bubbles! BUBBLES!

Importance of Self Documenting Code

What is self documenting code?

Let’s first take a look at code that is not self documenting.

var x = 1;
if (y === true) {
  x += 1;
}

vs 

let count = 1;
if ( loggedInSuccessfully === true ) {
  count += 1;
}

Even though this is a very simple example you can see right away that in the first example it is unclear what x is used for. You may be able to figure it out in context of the rest of the program but you might not.  In the second example it’s much easier to deduce that we are incrementing count every time someone has logged in successfully is true.

Now imagine this was a more complex function in the code.

function z () {
  let x = [];
  let y = _.keys(s);
  tables = _.map(y, function (y) {
    return function () {
       return z(y);
     };
   });
 return sequence(x);
}

vs

function createTables () {
  let tables = [];
  let tableNames = _.keys(Schema);
  tables = _.map(tableNames, function (tableName) {
     return function () {
       return createTable(tableName);
     };
  });
 return sequence(tables);
}

In this slightly more complex example there is only one clue as to what you might be doing in that first function. It’s the keyword sequence and even that just gives you a hint that they might be using the when promise library. This would require that either you wrote the horrible code so you know what it does or a decent amount of time trying to use it with in the code base.

The second one, well it looks like it wants to create a table based off an array of tables using the a function called keys to read the table names from a Schema variable. Then it builds that array by using a function called map to go over the tableNames schema, returning a function that calls the createTable function on the passed in tableName. Then we return the sequence output on that array we just finished building.

Even if that second paragraph does not make complete sense it will let you discuss the function with other programmers or support forums in a more intelligent way. That is the main benefit of self-documenting code, however it will also help you remember what you were doing when you have to revisit the code later.

One of the side effects of self-documenting code are potentially very long variable names. I have seen things along the lines of thisWillBeWhereWeStoreTheResultsOfTableCreationErrors. A bit hard to swallow but I have a pretty good idea what type of data I should expect to retrieve or store there.

Breaking it down

Reasoning

  • Create readable and understandable source code
  • Make it easier on the next guy (or your memory)
  • Keep code cleaner with less comments
  • Keep the documentation inside the code

Practices

The main goal is to make it as human readable as possible. Instead of single word variables use a phrase that is more closely tied to the meaning. The other aspect is to use white space to keep the structure consistent and reduce obfuscation of the algorithm being used.

Gotchas

 

There are things to watch out for, if working with a team, is to maintain uniformity, consistency and to make sure it doesn’t get too far out that it becomes a novel to go through your code.

If you stick to these basic guidelines you will do better than many professional developers out there. If you want to learn more head over to the wiki page.

Maker Square Day 5

Test Driven Development
Write a failing test, then code to the test. Go from Red to Green to Refactor. Why test? It changes the way you think about code. Forces the MVP thought process. Once you have an error, write a test.
Types of Testing
Unit Test – normally focus on 1 single method or class. Unit testing uses faked data.
Integration Test – ensures different parts of system work together like creating a customer, logging in a customer etc.
End to End test – make sure it works in real world test most realistic form of test. Start to finish, whole system. Think about smarter, less tests.
Visual Test – does it look like what it should look like?