arei.net ⇒ uncategorized
Writing Code for Other People

Writing code is hard. Getting code to work in a repeatable, consistent fashion that addresses all of the possible use cases and edge cases takes deliberate time and fortitude. Yet getting code working is only half the battle of writing good code. See, good code not only solves the problem, it does so in a manner that other people can use your solution to not just solve a problem, but use it to understand the problem, use it to understand the solution, and use it to understand how to go beyond it. Good code works, but great code teaches.

So, with that in mind, how do we as engineers, write great code? What separates code that merely gets the job done from code that empowers people who read it? How do we transform our code from simply functional to deliberately empowering?

Below I present my ideas on what makes code approachable to others. Following these techniques will make your code more readable by others, more understandable by others, and more reusable by others. To meet these goals requires four specific areas of your attention: readability, context, understandability, and re-usability.

Readability: Write Beautiful Code

The first step in writing great code is to make it readable to others. By the very nature of using a higher order programming language, one would think that readability is solved, but a programming language alone is not enough. A programming language, like any communication system, like any language, is merely a means to express an idea. It is how we use that language and how we structure that usage that makes it beautiful or not, that gives it real understanding.

1. Indentation Conveys Hierarchy

Most modern programming languages do not require indentation. You could simply write all your code like this:

function add(x,y) {
return x + y;
}

and it would compile and execute just fine. But clearly, there is a reason why most modern programming languages do allow for liberal indentation. This code with indentation is infinitely more readable:

function add(x,y) {
    return x + y;
}

We use indentation to indicate hierarchy. This works because of how we visual scan things with our eyes. Western language readers are taught to scan from top to bottom, left to right. Indentation plays into that. As you scan down the code from top to bottom, the left to right indentation allows you to easily ascertain hierarchy within the code.

The return statement in the above code clearly is subordinate to the function definition, merely by that act of indenting it.

In fact, beyond even most computer languages, most descriptive languages like HTML, XML, CSS, JSON, etc, all support indentation to imply hierarchy. One of the hardest things of all when inheriting someone else’s code or data is it not being well formatted. Reformatting and format commands work mostly, but not always, and that is where thing can rapidly fall apart.

2. Meaningful Whitespace

Indentation is not the only way we convey meaning in our code using whitespace. Consider this code:

const FS = require('fs');
const contents = FS.readFileSync(process.argv[2], 'utf8');
let lines = contents.split(/\r\n|\n/);
lines = lines.map(line => {
    line = line.toLowerCase();
    line = line.replace(/[^\sA-Za-z0-9-]/g, '');
    line = line.replace(/\s\s|\t/g, ' ');
    return line;
});
lines = lines.map(line => line.split(/\s/));
const words = lines.reduce((words, line) => {
    line.forEach(word => {
        words[word] = words[word] + 1 || 1;
    });
    return words;
},{});
Object.keys(words).forEach(word => {
    console.log(word + ' ' + words[word]);
});

Like our indentation, this is perfectly executable code that will run and do the several “things” it is intended to do. But understanding what those “things” are is not so clear.

Code runs in an organized top to bottom fashion, and we mostly structure that code into logical steps. The code reads a file, the code breaks the file contents up by newlines, etc. These are the steps that your code performs.

If you look at this code you can even begin to see each of these steps. It might take a minute or two, but the steps are there.

Now, look at this code again:

const FS = require('fs');

const contents = FS.readFileSync(process.argv[2], 'utf8');

let lines = contents.split(/\r\n|\n/);
lines = lines.map(line => {
    line = line.toLowerCase();
    line = line.replace(/[^\sA-Za-z0-9-]/g, '');
    line = line.replace(/\s\s|\t/g, ' ');
    return line;
});
lines = lines.map(line => line.split(/\s/));

const words = lines.reduce((words, line) => {
    line.forEach(word => {
        words[word] = words[word] + 1 || 1;
    });
    return words;
},{});

Object.keys(words).forEach(word => {
    console.log(word + ' ' + words[word]);
});

The logical steps of our code are much clearer to see, much cleaner to read. The only change between the two examples is whitespace.

This process of visually splitting logical steps of code up is called meaningful whitespace. Meaningful whitespace is the art of using well placed line breaks to chunk code into discreet steps. Just like indentation, we use whitespace, new lines, to organize the logic of what our code does for other people to easily understand. And this is about more than just breaking up large chunks of text. Smaller blocks of code are easier to understand when examined than larger ones. Visually when reading this code one can easily understand that each of these steps does something in common and works together to achieve some result.

This is another reason that most programming languages ignore whitespace.

When inheriting someone else’s code it is not uncommon to find a complete lack of meaningful whitespace. The burden this places on the developer to go through the code and chunk it up correctly is significant and slows down their rate of understanding. By grouping your code into chunks that are digestible and understandable to someone else you aid them in time to understanding.

Context and Comments

Up to now we’ve talked about how to make our code more readable. Indentation and Meaningful Whitespace provides readers of your code super easy cues to help the scan and breakdown your code and this makes the code more readable. Readability is the first key to great code.

The next step to great code: context. That is, once my code can be easily read, how do I give it meaning so it can be easily understood. And the keys to understanding code is understanding the context of what any section operates within and on, and how the logic flow of any section operates.

3. Contextual Naming

Fun fact, excluding comments and data, the only things in your code that you get to name are classes and variables and functions. Everything else is a pre-defined keyword or operator of some type. This is why class and variable and function naming is so important, because it is the only part of your actual code where you can provide context to what your code does.

Consider the following code:

function x(y) {
   return y < 1 ? 0
        : y <= 2 ? 1
        : x(y - 1) + x(y - 2);
}

What this code does is not obvious by just reading the code. Providing a contextual name to the function changes everything here:

function fibonacci(y) {
   return y < 1 ? 0
        : y <= 2 ? 1
        : fibonacci(y - 1) + fibonacci(y - 2);
}

Class names, function names, variable names, these are opportunities to describe what they represent (classes), what they do (functions), and what they hold (variables). The name provides context to the role in the system.

Now, there are a few special rules around this, for sure. If iterating a number in a loop, we use i for the index. This is a well-known convention. But even this convention can stand breaking some times. If the context is more important than the convention, always go for more context.

4. Convey Logic through Comments

Class names, function names, and variables names all provide context as to their roles, but program logic is dictated by keywords and in almost all programming languages there is no way to change keywords. So how do we provide context and meaning around program logic?

That is where comments come in, and specifically inline comments within the code. I view this differently than documentation. Documentation answers the bigger question about the code purpose and how people use the code. Comments, instead help to describe the logic and the context around the logic in the code. (We will talk about documentation in greater detail in a little bit.)

Comments within your code are simple useful hints as to how the logic within the following section of code works. Have you ever read a block of code and then wondered to yourself what is going on? That is a failure of commenting. The initial author failed to recognize that another developer would understand the code, and that stems from either hubris or laziness, neither of which are particularly good habits to have as a developer.

Now, this is not an advocation for writing a comment before every line of code. I am a firm believer in writing code that is simple to follow and does not require comments to understand, but that is not always the case. And over-commenting creates a whole separate level of problem. Instead, comment where it is needed. When considering any section of code (which you nicely formatted with whitespace), ask yourself “is it readily obvious what it does?” If the answer is even slightly a no, take a second to add a comment or two of context.

This code from an earlier example is a lot more understandable for a handful of comments, and adding these comments as the logic is written takes almost nothing:

// Bring in the standard filesystem library
const FS = require('fs');

// Read the file
const contents = FS.readFileSync(process.argv[2], 'utf8');

// Split our file content into lines and
// convert each line to an array of simple words
let lines = contents.split(/\r\n|\n/);
lines = lines.map(line => {
    line = line.toLowerCase();
    line = line.trim();
    line = line.replace(/[^\sA-Za-z0-9-]/g, '');
    line = line.replace(/\s\s|\t/g, ' ');
    return line;
});
lines = lines.map(line => line.split(/\s/));

// Count the occurance of each word in all the content.
const words = lines.reduce((words, line) => {
    line.forEach(word => {
        words[word] = words[word] + 1 || 1;
    });
    return words;
},{});

// Output our word cloud and frequency 
Object.keys(words).forEach(word => {
    console.log(word + ' ' + words[word]);
});

There are two different uses of comments. First is what we covered above, to add logic understanding to your code. The second use of comments is to add documentation around how your code is used. This second type is covered in a later section, so please keep reading.

For logic comments, the general rule of thumb is to use // instead of /* */ in your code. /* */ block style comments are really more for providing documentation than doing quick one-off logic comments.

Also, when doing logic comments, do not hide them on the end of a line. Put them on their own line so that they are more visible and easier to see.

const superWeirdThing = !superWeirdThing; // DON'T COMMENT LIKE THIS

Organize Your Code

Understanding about your Code is done partially through providing context about what that code does, but equally important to understanding is organizing and structuring your code in a repeatable, understandable, and accepted fashion.

5. Organized from Top to Bottom

The first step in organizing your code is to physically lay the code out in logical sections. Almost all modern programming languages have a recommended approach to organizing your code. Different languages have different approaches to this, and even different approaches within that. JavaScript, is one of the more chaotic languages with little formal agreement on the best way to do this. However, there are still little things you can do without a formal community accepted standard. For example, import/require statements are expected to be first in the file.

The important thing here is to keep like with like. Do not put two class definitions separated by some variable assignments. Put the class definitions together. This is an implied structural organization for your code and it applies at the file level, the class level, and the function level.

A common layout pattern for a file in many languages is:

  • Require Libraries
  • Declare Constants
  • Declare Variables
  • Declare Classes
  • Declare Functions

A common layout pattern for a class in many languages is:

  • Declare Static Members
  • Declare Members
  • Declare Static Methods
  • Declare Constructor
  • Declare Methods

There is a common layout pattern for writing functions in some languages, but JavaScript is a little more lose here, so I am not going to offer a formal pattern. Instead, I will tell you how I like to structure things for a function:

  • Arguments and Argument Checking at the top
  • Declare variables as I need them, but nearer to the top if possible.

6. Separation of Concerns

In computer science the concept of Separation of Concerns (SOC) allows one to divide a computer program into logical sections based on what each section of that computer program does. In Web Development, HTML, CSS, and JavaScript is an example of Separation of Concerns where HTML is responsible for the content, CSS is responsible for how the content looks, and JavaScript is responsible for how the content behaves. Model-View-Controller (MVC) is yet another Separation of Concerns system that is often used.

But beyond a fancy CS Degree, separation of concerns means creating one thing to do that thing well without side effects. It means writing many functions that each do something well, instead of one single function that handles all the cases. It also makes more sense to break things up into smaller discreet units in terms of reusable code.

It also means letting the various pieces do exactly what they are good at and not trying to force them to do tasks that are better suited elsewhere. It is this reason that we should not write style information in JavaScript when a perfectly good CSS rule will do. CSS is optimized for dealing with these things and JavaScript is not, so why would you try to outwit it? Of course, there are always times when you have to break these rules, but they are very, very rare.

Related to SOC, in Computer Science there are three other principals to be aware of:

  • Coupling – Coupling is the measurement of how interdependent two modules or sections of code are to one another. There are a lot of types of coupling between two sections of code with a lot of fancy names and descriptions. For now it is best to just understand it this way: How dependent on A is B and vice-versa? Can A run without B? Can B run without A? Two modules are said to be Tightly Coupled, if they are very dependent on each other. Conversely, they are said to be Weakly Coupled it they are only slightly dependent on one another. Coupling in code is necessary because code executes linearly. However, designing classes and functions to be independent provides for better re-use and more understandable code. Consider some code you are looking at and that moment when you say, “Well, this calls function X, now where is function X and what does it do?” This is an example of coupling.
  • Cohesion – Is somewhat the opposite of coupling as it measures the degree to which things within a section or module of code belong together. This is usually described as having High Cohesion, meaning things within the module belong together, or Low Cohesion, meaning that they do not. In Object Oriented Programming, high cohesion of what is in any given class is a design goal. The class should do what it sets out to do and only what it sets out to do. If I have a Class called Car and inside that class there’s a function called juggle() it probably means my class has poor cohesion (and interestingly probably also implies tight coupling with something else). Side Effects from running a module or function implies poor cohesion. If function juggle() also fills the car with gasoline, either this is an amazing juggling trick, or there is a side-effect in the code.
  • Cyclomatic Complexity – Cyclomatic Complexity is the measure of how complex a section of code is, based on the number of paths through the code. That is to say, the more non-linear outcomes the code generates, the higher its Cyclomatic Complexity score. This is often judge by the number of conditional statements in your code. A function that has no conditionals, is said to have a Cyclomatic Complexity of 1. If it had a single conditional with two out comes (a typical if/else for example) it would have a Cyclomatic Complexity of 2, and so on. Cyclomatic Complexity is not bad, in and of itself, but the more complex the code, the higher the possibility of failure, and the more testing required. A function should strive for a lower complexity score if possible.

So, we talk about these three measures of code in order to reinforce the point of Separation of Concerns. A Separated module is one that is not coupled directly to another module, is cohesive in what it does, and reduces complexity.

When you find yourself in code that is hard to follow, it is almost always because it fails on one of these three factors.

One way to reduce complexity and structure your code better is to identify the cohesive sections of your code and isolate them into Logical Blocks. A Logical Block is a portion of your code that requires multiple lines to complete a single task. As we talked about earlier, breaking your code up with meaningful whitespace makes these logical blocks easier to identify. Adding comments makes them clearer in their purpose.

But a Logical Block also is a good hint as to how to abstract logic into small, more cohesive behaviors. For example, if your logical block needs to get reused, isolate it out into a new function.

Also, it is worth mentioning about Code Folding. Code Folding is a feature of most modern IDEs that allow you to hide (or fold) blocks of code. Code Folding in your IDE can be a powerful code reading tool. However, Code Folding requires certain syntax structures to work. By thinking of your code as Logical Blocks you can see where Code Folding opportunities could exist, if the logical block was in an acceptable structure.

Thinking about your code as a Logical Block allows you to more easily see other ways to do the same thing, ways that may be cleaner and more cohesive. It illustrates where there may be room for improvement in your code as well.

For example, this code is a Logical Block.

let sum = 0;
for (const num of numbers) {
    sum += num;
}
const avg = sum / numbers.length

You could change this logical block to be more readable by…

  • Abstracting it out to a function, especially if it is going to be reused.
const avg = calculateAvg(numbers);
  • Wrapping it in a IIFE (Immediately Invoked Function Expression)
const avg = (() => {
    let sum = 0;
    for (const num of numbers) {
        sum += num;
    }
    return sum / numbers.length; 
}());
  • Using a built-in library to do it simpler.
const avg = numbers.reduce((sum, num) => sum + num, 0) / numbers.length;
  • Using a third party library helper function.
const sum = _.avg(numbers);

All of these are better than the first because they create an isolated block that cleanly identifies what it does. With proper whitespacing and a comment above the block, makes this tight, readable, well reasoned code.

Code Usability

At some level, everything you see, smell, taste, touch, or interact with is a User Interface. An API, for example, is a User Interface between your backend and your frontend. This goes for the code you write as much as anything else. At some point, another person is going to read your code, run it, and even have to make sense of it. So, build your code like you would an API. Take into consideration how another person is going to interact with that code, how they are going to try and reason about it, how they are going to try and work within it.

Build everything with another user’s experience in mind.

7. Defensive Coding

Software is a piece of code that produces some sort of output, usually based on some sort of input. Now, assume someone is going to run your code at some point. Assume that that person is not going to read the documentation. What would happen? Would it work if the first argument is a null? Would it work if the second argument was a negative zero or a NaN? How your code behaves when executed under uncertain conditions is a testament to the quality of engineering employed in building it.

An approach to handling these questions is called Defensive Programming. In defensive programming you assume that users will maliciously try to cause problems with your code and therefore your code must guard against their attack. This means making the assumption that all data is tainted and must be verified to be correct.

Here’s an example:

if (this.onClose) this.onClose();

The assumptions made by this code are not defensive. The snippet assumes that onClose is a function and then executes it as a function. A corrected version of this code might look like this:

if (this.onClose && this.onClose instanceof Function) this.onClose();

But there is another assumption here as well, that executing this.onClose() will work? So even more defensive code might do it thus:

if (this.onClose && this.onClose instanceof Function) {
    try {
        this.onClose();
    }
    catch (ex) {
        ... do something about the error ...
    }
}

There is even an argument, that another defensive point might be that if this.onClose() is a long running process, it could cause your thread execution to grind to a halt and an even more defensive posture might be thus:

if (this.onClose && this.onClose instanceof Function) {
    setTimeout(()=>{
        try {
            this.onClose();
        }
        catch (ex) {
            ... do something about the error ...
        }
    },0);
}

That last form might not work for all situations, but it is extremely defensive.

The key to writing code defensively, is to checking your inputs early in your code. Make sure what you are getting is what you are expecting. If your function only works with even numbered integers, you better make sure it takes only even numbered integers.

The same is true for classes. Write your classes to assume that users are going to try to harm them and break your code. This means writing defensive methods but also, preventing unwanted or unknown class state mutation. Setters are a great way to protect your class from bad user input and should be used whenever possible instead of exposed public members. Consider this class:

class Car {
    make: 'Chevy';
    model: 'Malibu';
    mpg: 25;
    tankSizeInGallons: 14;

    toString() {
        return `The ${this.make} ${this.model} can go ${this.mpg * this.tankSizeInGallons} miles on a single tank of gas.`;
    }
}

The publicly exposed make, model, mpg, and tankSizeInGallons are all mutable without any thought for defensiveness. A malicious coder could cause quite a problem with these variables. More defensive style would be to use private variables (or Symbols) to hold the values, and provide public getter and setter functions to expose them. The setter functions, in particular, can do error checking and ensure type and values match acceptable inputs.

8. Code is a User Interface

Your code, whether a component, a utility, or an API, is going to get used by someone else. This is even more true when one considers that sharing of code online has become pervasive. And if you work in a team setting at all, this compounds the likelihood someone else will need your code. I do not care how throw away you believe your code is, assume that someone is going to use it.

To that end, and as stated before, treat your code like a User Interface. This means designing your code to be read is important, but also designing your code to be used by others is equally important. Ask yourself how another user is going to come in contact with your code. If they see the function signature, does it provide enough information as to what it does and how it works or does it require additional information? If they read your code, is it obvious how they would step through it from line to line or does it require more contextual logic?

A lot of what we have already covered in this document describes how to address writing code toward usage by others, but it bears repeating here:

  • Design your code to be read by others.
  • Highlight hierarchy with indentation.
  • Separate discreet sections of behavior with whitespace.
  • Name classes, functions, and variables contextually.
  • Provide comments around programming logic.
  • Clearly Separate your application concerns.

Following these steps is the first part of writing code like a user interface.

The second part is to always be asking yourself, how will others use my code? Challenge yourself to always be mindful of this question and your code will be the better for it.

Most professional coding work is a shared environment where everyone is always working on each other’s code; any team experience really is. As such it is critical to always be considerate of how others are going to use your code. Whenever you write a new component you should be consciously aware that someone else may very well need what you are building for their own purposes. Write your component with that reuse in mind. But also, be insatiable in your desire to make your component as accessible to another developer as possible. The more we reuse one another’s components, the better our product becomes.

9. Documentation

Finally, let us talk about documentation. To many software engineers the act of writing documentation is seen as an after thought, something to be farmed out to some loser English Literature person desperate for a job. But the reality of software engineering is that it is only 50% about writing code. The remaining part of Software Engineering is communicating with other people.

As we have stated above: someone else is going to use your code. It is inevitable. Given that, telling those users how to use your code is critical. If you fail to communicate how your code runs, you might as well not have written the code at all.

We talked about comments in a prior section. Comments are used to describe the logic your code follows. Documentation, on the other hand, describes how a user of your code interacts with the code and gets it to do what is expected.

Unlike inline comments to describe logic blocks, documentation is about describing the interfaces of your code, the places where others will interface with your code. We write documentation to tell others whom are using the code what it does and how it is used. This does not mean you document every single function and variable. Instead this means you document every public facing part of your code, every place other will interact with it.

Fortunately, in this day and age, you do not even have to lift your eyes out of your IDE to write documentation. Any modern language today has an associated documentation language built into it. Java has JavaDoc, Typescript has TSDoc, JavaScript has JSDoc, etc. These documentation languages assist you in describing your class, function, variables, every aspect of your code as much as you want.

Even better, most modern IDEs have these documentation languages built right into them and have tooling that makes writing that documentation easier.

Here’s an example of using JSDoc:

/**
 * Move the selection to the "first" section.
 * @return {void}
 */
selectFirst() {
    const first = this.sections.find(section => section.startHere);
    this.select(first || this.sections[0] || null);
},

In this example the comment block that precedes the selectFirst() function describes what it is and what it returns.

Documentation languages vary by programming language, so please read up on your particular one.

One note about documenting that to address: Your code is not self-documenting. Many, many people have said this over the years and every single one of them has been wrong. What they are really saying is their code is Readable and that is enough. In some case this is true, but mostly it is not. Please add documentation to your code about what it does and how it is used.

Denouement

So that’s it. Above we outlined nine (9) separate ways to make your code more readable, more descriptive, more defensive, and more user friendly. It’s a lot, to be sure, but each of these approaches is a small step towards the larger goal of writing better code that is more than just runnable.

We recognize that this could be seen as a lot. We all know that software is a demanding job full of demanding bosses and customers who think it is super easy. And these best practices they take additional time, they cost cycles, and adding them can seem overwhelming. However, starting small is the key here. When considered as a whole, these rules can seem daunting. But individually, they are not so rough. Try adopting one or two of these at first, then a few weeks later add another, until they are all second nature. It’s a good bet you are probably already doing one or two of these without even thinking about it. So, add a few more, then a few more, and next thing you know you will be shipping code you are proud to have others to read.

permalink: http://www.arei.net/archives/302
Introducing ZephJS

We are pleased to announce the release of ZephJS!

ZephJS is an extremely easy to use, simple to understand, ultra-light framework for defining and using Web Components. ZephJS is perfect for people writing component libraries, teams building applications or sites that just require a few custom components, or projects building whole applications that do not want the gigantic weight of a modern JavaScript browser framework. ZephJS simplifies the process of defining custom Web Components into a highly readable declarative structure that uses standard JavaScript, standard HTML markup, and standard CSS styling. And ZephJS weighs in at less than 20k minified!

Here’s an example of using ZephJS to build a customized button:

my-button.js
import {ZephComponents} from "./zeph.min.js";
import {html,css,attribute,property,bind,onCreate,onEvent} from "./zeph.min.js";

ZephComponents.define("my-button",()=>{
    html("./my-button.html");
    css("./my-button.css");

    attribute("icon","");
    attribute("icon-placement","left");
    attribute("disabled",undefined);

    property("clickCount",0);

    bind("@icon","button > img","@src");
    bind("@disabled","button");

    onCreate((element)=>{
        console.log("Element '"+element.getAttribute("name")+"' created!",element);
    });

    onEvent("click",(event,element)=>{
        if (element.hasAttribute("disabled")) {
            event.stopPropagation();
            event.preventDefault();
            return;
        }

        element.clickCount += 1;

        console.log("Button '"+element.getAttribute("name")+"' clicked "+element.clickCount+" times.");
    });
});

ZephJS uses modern, standard JavaScript to make writing Web Components super easy to do. There is no mucking about with Shadow DOM or figuring out how to add encapsualted styles; Zeph handles all of that for you. Want to add an attribute to your Web Component? Zeph has you covered with its attribute() declaration. Want that attribute to update a component in your Web Component’s internal content? Zeph has you covered with support for Attribute/Property/Content binding. Want to handle a click event on a button nested in your Web Component’s internal content? Zeph makes it easy to do so. Zeph provides all the tools you need to define and use modern Web Components.

How ZephJS Works

At the heart of ZephJS is the ZephComponents.define() method to which you provide the name of your component and the definition of that component. The definition is a standard JavaScript function within which you call a number of declarative definition methods to describe the content, style, and interactions of your Web Component.

The definition methods you call builds what ZephJS calls a “context” that describes the Web Component. It uses this context to create a unique class which is used with the Custom Elements API to register the Web Component for usage in your HTML. When the registered component is created (via tag usage or document.createElement()) the constructed class constructor is called and ZephJS populates the component as described in the context.

Definition Methods

There are currently seventeen different definition methods for you to describe your Web Component with ranging from providing HTML and CSS to handling events. Here are the some of the most useful…

html() is used to add the internal content of your Web Component, that is all the HTML that makes up the inner workings of your component.

css() is used to associate a set of internal CSS style rules to your content. These rules can target the internal content (provided by html() above) or the created element itself (with the :host and :host() psuedo-selectors.)

attribute() adds an attribute to your custom element and associates an initial value with that attribute.

property() adds a property to your custom element and associates an initial value with that property.

bind() and bindAt() are used to watch for attribute/property/content changes in your element and then propagate the changed value to some other attribute/property/content of a different element. (See “Bindings” below.)

onInit() / onCreate() / onAdd() / onRemove() / onAdopt() all allow you to provide a callback function to execute when certain ZephJS Lifecycle events occur. For example, onAdd(myAddHandler) would execute when the element is added to some Document or DocumentFragement.

onAttribute() is used to execute a callback if a given attribute on the element is changed.

onProperty() is likewise used to execute a callback if a given property of the element is changed.

onEvent() and onEventAt() are used to execute some callback handler when a given event (like a mouse click or a keystroke) occurs.

There are a few other definition methods, but these are the key ones. If you want to know more, check out the ZephJS Quick Start guide or the ZephJS API documentation

Inline vs Separated Content

With both the html() and css() definition methods you may either provide the content inline as a string, or you may provide a URL or relative filename. If the latter, ZephJS will go out and load the URL or relative filename and use that as the content for the call.

ZephJS highly recomends you use the relative filename approach. This allows you to separate your code, content, and style information cleanly.

Additionally, ZephJS provides a bundler tool that will read your component(s) and all of the associated html() and css() file references and bundle them into a single usable JavaScript file for production systems or distribution. This means keeping your code clean and separated can be done without impacting your external performance.

Bindings

Due to the ZephJS design goal to “Never try to outwit the browser”, ZephJS does not provide inline binding template strings the way most of the big JavaScript frameworks do. However, ZephJS does provide bindings rooted to the element or an element within the web components internal content. To do so you provide the source element you want to watch, what you want to watch on that source element (attribute, property, or content), the target element to propagate the change to, and what on the target element to propagate to (attribute, property, or content).

Here are a few examples:

bind("@value","div > input.username","@value");

This would bind the Attribute “value” on the custom element to propagate any changes to the attribute “value” on the element “div > input.username” within the internal content.

You could even shorten this by dropping the last argument; ZephJS will use the source name (“@value”) for the target name, if not provided.

bind("@value","div > input.username");

Here’s another example:

bindAt("button",".clickCount","div > span.counter","$");

This would bind the property “clickCount” on the “button” element to propagate any changes to the content (specified here as “$”) of the “div > span.counter” element.

Bindings use a special notation to determine if you are refering to an Attribute, a Property, or the content of an element, but once you understand the rules of the notation it is pretty easy to read:

  • An Attribute is prefixed by the “@” character as in “@value”.
  • A Property is prefixed by the “.” character as in “.value”.
  • The content of an element is specified by the entire string “$”.

Bindings are a really simple, but highly useful way to move information around in your Web Component without having to worry about all the boilerplate details to do so. It is yet another example of how ZephJS tries to simplify the heavy lifting for you.

Events

When you are defining a Web Component you are defining the details about an element that will be created later. As such, adding events around those elements is normally non-trivial. ZephJS, however, makes it super easy with the onEvent() and onEventAt() definition methods.

First, you tell ZephJS what element you want to watch for events: the onEvent() method watches the custom element itself, while the onEventAt() method takes a CSS Query Selector string as its first argument and matches it against any element within its internal content.

Next, of course, you give the name of the event you want to watch for, such as “click” or “keyup” or “dragstart”. Any event that would occur on an element can be used.

Finally, you provide a callback function to execute when the event occurs. This callback function receives the event object, but it also receives the custom element itself and the internal content, allowing you to interact with all the pieces of the web component.

Getting Started

So that is the basics of ZephJS the extremely easy to use, simple to understand, ultra-light framework for defining and using Web Components. We have covered all the key features of ZephJS, but there is, of course, lots more. Fortunately ZephJS has provided a ton of documentation to read and learn about all the in’s and out’s of building Web Components.

We recommend you get started here, with our Quick Start Guide:

But if you are more interested in a specific area…

Naturally though, there is no better way to learn ZephJS then to roll up the proverbial sleves and try it out…

You can start by checking out the ZephJS repository. From there you can learn all about the details of ZephJS including how to install it and get started using it.

Reaching Out

We are super excited about ZephJS and really want to hear from you. Feel free to drop us a line, file a bug, submit a PR, whatever. We would love to hear what you are doing with ZephJS and all the multitude of ways you find it cool.

permalink: http://www.arei.net/archives/295
JSConf 2013 Beach Ultimate Frisbee Game

Want to getaway from the conference and get some exercise? Do you know or want to learn what a huck is? Do you want to physically do a layout instead of building one in CSS?

Come play some Beach Ultimate Frisbee!

Join like-minded individuals on Thursday, May 30th from 5:00pm until dark as we toss the disc about and hopefully, if we get enough interest, have a sweet game of Beach Ultimate. I’ll bring the cones and discs, you just need to bring a White and a Dark shirt (Grey does not count as either).

We’ll be playing out on the beach at roughly the location marked on this map, but I really have no idea what the beach conditions or obstacles might be. Even the layout of the resort is a bit of a mystery, so just head out past the pools to the beach and look for the floaty white disc being thrown.

This will be entirely friendly and uncompetitive, just trying to have some fun. If you do not know how to play Ultimate Frisbee, feel free to join in and I will teach you the basics about an amazing sport I love to play. Just let me know if you want some pointers.

If you have any questions, please send an email to jsconfulti /at/ arei /dot/ net or hit me up on twitter (@areinet).

permalink: http://www.arei.net/archives/272
Hiring Cleared JavaScript Developer, Ellicott City, MD

Generally I avoid recruiting people on behalf of my company, but they have recently asked me to hire a person to work directly for me and to hopefully even replace me in the future.  And, quite frankly, I’m tired of interviewing people brought to me by the company recruiter who have no understanding of what is really involved in writing code.  So, I wrote this way more interesting sounding job description and now I’m looking to find someone to fill it.  Are you that person? Know someone whom is that person? Let me know with a quick email sent to vstijob/at/arei/dot/net.

Are you an up and coming hot shot Web Developer who somehow ended up working on government contracts?  Are you horrified by the state of technology that the government contract you are working on has saddled you with using? Do you wish that your project would stop supporting browsers that are 11 years old and move into the future? Do you want to move beyond writing JSPs, Web Services, and XML? Are you ready to give into the dark gibbering madness that comes with embracing technologies like JavaScript, CSS3, JSON, and NodeJS? Are you ready to awesome-ify your career?

VSTI, A SAS Company, is looking to hire a Junior to Mid-Level Web Developer/Engineer and we want it to be you. Well, we want it to be you if…

  • You have a good basic understanding of JavaScript and are ready to learn a lot more.  And by ‘basic understanding’ we mean that you know what a closure is and how to write one in JavaScript, but you really want to understand why this makes JavaScript so powerful and all the really cool things you can do now that you know what a closure is.  We’re not looking for a JavaScript expert, but someone who wants to become a JavaScript expert.
  • You know more about HTML/CSS than just how to write tags and believe that 90% of HTML should be written using only DIV tags and some amazing CSS. In fact, you should be able to tell the difference between block and inline elements at a glance.
  • You find the possibility to use cutting edge technologies like NodeJS and ElasticSearch to be darkly enticing. In fact, just the act of us mentioning that you could work with those technologies makes you giggle like a mad scientist.  After the giggling has died down you decide to go read the documentation just for fun.
  • You have a serious passion for technology and want to learn more, a lot more.  Ideally, you wish you could learn everything through some sort of cybernetic implant process, but you realize that you still haven’t invented that yet and the only way to learn is to read and to get first-hand experience.

Here’s the obligatory job posting details…

  • You must be willing to work in Ellicott City, MD on a daily basis.  No telework is possible.
  • You must have an up to date TS/SCI Full Scope Polygraph clearance.
  • You must have a solid understanding of JavaScript, CSS, and HTML.
  • You must be willing to be figuratively thrown into the fire.
  • You must be passionate about learning new stuff.
  • You must desire to become an expert in Web Technologies.
  • You might also have an understanding of any of the following… Java, Groovy, Ant, Grails, more than one JavaScript frameworks (like jQuery or Prototype), Agile/Scrum/Kanban, CSS Resets, SVN, Hudson, CSS3, Rally, Apache Tomcat, or Git.
  • If you have a Github account, a blog, or an active twitter account that will help your cause greatly.
  • You might also be competent with some art software like Adobe Fireworks or GIMP, but it’s not a requirement.

In return for all of this VSTI, A SAS Company, will provide you with the following…

  • A very competitive salary.
  • Amazing benefits that you not likely to get elsewhere.
  • Small company feel, Large company resources.
  • An amazing chance to learn and grow your skills.
  • Patriotic pride in what you do (since this is a government contract after all).
  • The opportunity to be part of a team where your opinion is valued and taken into consideration.
  • The possibility of free beer if you like that sort of thing.

So, if any of this sounds cool to you then you should apply for a job.  We’re interviewing now and we’re looking to hire very quickly.

permalink: http://www.arei.net/archives/260
node-untappd v0.2.0

Just a quick note to say that last night I released to Github and NPM v0.2.0 of node-untappd, the Node.js connector to the Untappd API.  This new version supports the latest v4 of the Untappd API including OAUTH authentication.

Lots more details at Github: https://github.com/arei/node-untappd

permalink: http://www.arei.net/archives/258
Introducing functionary.js

I am pleased to release another open source project, functionary.js.

functionary.js is a simple JS polyfill and enhancement for adding additional behavior to functions.  Fundamentally, it allows developers to modify and combine functions into new functions to develop novel patterns.  It is very similar to sugar.js, prototype.js, and the jQuery Deffered object and behavior.  It is sort of like Promise/A but not really like it at all.

Functionary is a prototypical modification to the Function object.  This may cause some users considerable consternation as there is some belief that JavaScript should not be used in such a manner.  I, however, believe that JavaScript was actually designed to do this very thing and should do it albeit with great care.  That said, functionary.js never will overwrite a function of the same name on the Function Prototype.  So if Function.prototype.defer is already created by another Library (like Prototype JS) functionary.js will not overwrite it, but use it instead.

functionary.js works in both browsers and node.js implementations.  However, functionary.js does modify the global Function prototype and should be used with care and full understanding.

It breaks down into two distinct classes: Threading enhancements and combination enhancements.

For purposes of the following discussion, the following things are true:

var f = function() {};
var g = function() {};
var h = f.something(g);

In the above example, f is the bound function of something and g is the passed in function.  Understanding this will help the discussion below be more clear.

Threading Enhancements

While javascript is inherently single-threaded, it is possible to create threaded like behavior using the single thread model and eventing.  This is not a replacement for true multi-threading, but an okay approximation and the fundamental underpinning of javascript and node.js.  functionary.js provides a set of function modifiers for working within the confines of this “threading” environment to produce cleaner and expanded function behaviors with regards to threading and event behaviors.

The following functions fall into this group: defer, delay, collapse, and wait. defer and delay will be familiar to many JS developers, but collapse and wait are the really interesting additions.

collapse basically will collapse multiple executions of a function (call it f) into a single execution. So regardless of the number of times you call f() the actual execution will only happen once… the executions are collapsed into a single execution.  collapse can be used in one of two forms: Managed or Timed.  In Managed mode, the execution of a function is not actually performed until manual execution of the f.now() is called.  Thus repeated calls to f() are short circuited until f.now() is called.  In Timed mode, the execution of a function is automatically performed x milliseconds after the first call to f() and then everything is reset.  This ensures that execution happens based on some period of time.

wait is used to defer execution of one or more functions which are passed as parameters to wait.  Once all those functions have been executed, regardless of results, the bound function of wait is executed.  In the following example f.wait(g,h,i) wait allows a developer to defer execution of function f() until g, h, and i have all executed.

Combination Enhancements

The other aspect of functionary.js is to provide some simple ways to combine functions with other functions in a clean and concise manner.  Sure, it is possible in unmodified javascript to combine functions, but functionary gives you a more clear way to do this.

At the core of this group of functions is bundle which takes the bound function and combines it with the passed in function(s) to produce one single function.  Think of it as taking function f and function g and bundling them together into function h.  Calls to function h then execute f and g in that order.  While in some cases it’s easy enough to just call f and g directly, in others being able to pass a single function like h can be incredibly useful.  Consider this:

var f = function() {};
var g = function() {};
var h = f.bundle(g);
h.defer();

The last line of this code ensure that f and g run together, but after being deferred.

Other functions include chain, before, and after.  These functions are all, in essences, some form of bundle above, although with different orders of execution.

functionary.js provides two new functional wrappers, completed and failed.  completed ensures that the passed in function will only execute if the bound function returned without an exception.  failed is the converse and will ensure that the passed in function will only execute if the bound function DID return an exception.  These two functions offer a unique approach to try/catch paradigms.  Coupled with bundle, a try/catch/finally model is easily possible as shown:

var compl = function() {};
var fail = function() {};
var fin = function() {};
var f = function() {};
var h = f.completed(compl).failed(fail).bundle(fin);

Finally, functionary.js offers a wrap function akin to sugar.js and prototype.js where once can wrap the passed function around the bound function.

Documentation

Please see the documentation on github for all the details of using these functions.  Also, play with the code, it probably won’t bite.

Installation and Details

You can get functionary from github.  I encourage you to check it out, fork it, and submit changes.  The ultimately goal is to make functionary the go to polyfill/add on to JS for functions.

 Thoughts, Comments, Suggestions?

If you have thoughts, comments or suggestions, please put them on github or contact me on twitter at @areinet

permalink: http://www.arei.net/archives/254
Tweet and Like

Today I removed comments from the site. I replaced them with tweet and like (facebook) buttons. Although I still maintain my stance that Facebook is dumb. Twitter on the otherhand, is the awesome.

So, if you see something you like here, tweet about it. Or Like it if you swing that way.

permalink: http://www.arei.net/archives/229