This is the first of a series posts in which I will be building an Alexa Skill. I haven’t pre-written this series, so I don’t know where it’s going to end up, or even the exact steps that will occur along the way. What it will be is something closer to how development would occur in the real world as opposed to a sanitized tutorial.

The skill I’ll be building is one for my church. It will let users ask for the time of the next service or event. You can also ask it for the church address and phone number. And we’ll see what other interesting things we can add. If you dislike church’s for some reason, feel free to substitute your favorite civic organization :wink:.

Getting Started

Here are the prerequisites for the tutorial:

  1. An AWS developer account.
  2. You know or can follow along when explaining code in JavaScript.
  3. You have Node.js installed. Let’s go!
  4. If you would like a tutorial for configuring the environment from scratch, let me know. I’ve found this information easily enough with Google that I didn’t think I needed it here. When I write a complete book, I should probably include it (right?).

Install the Alexa Skill Kit Command Line Interface (ask-cli)

npm install -g ask-cli

Initialize the ask-cli

ask init

Create a new skill with the ask-cli

ask new -n sotv

skill.json

At the top level of the project, a file called skill.json is created. This file contains the skill manifest (Skill Manifest API) and is the JSON representation of the skill.

{
  "manifest": {
    "publishingInformation": {
      ...
    },
    "apis": {
      ...
    },
    "manifestVersion": "1.0"
  }
}

The publishingInformation object describes how the skill is presented to end users in the skill store or Alexa app. The supported locales, description, category (list of categories), and other information is contained as shown below.

...
"publishingInformation": {
      "locales": {
        "en-US": {
          "summary": "Sample Short Description",
          "examplePhrases": [
            "Alexa open hello world",
            "Alexa tell hello world hello",
            "Alexa ask hello world say hello"
          ],
          "name": "base",
          "description": "Sample Full Description"
        }
      },
      "isAvailableWorldwide": true,
      "testingInstructions": "Sample Testing Instructions.",
      "category": "EDUCATION_AND_REFERENCE",
      "distributionCountries": []
    },
.//

The apis object describes the HTTP endpoint that processes the intents that the skill supports. The apis object shown below configures the endpoint to be an AWS Lambda function that is defined in the lambda/custom directory of this project.

...
    "apis": {
      "custom": {
        "endpoint": {
          "sourceDir": "lambda/custom"
        }
      }
    },
...

The manifest can also contain (privacyAndCompliance)[https://developer.amazon.com/docs/smapi/skill-manifest.html#privacyandcompliance], (permissions)[https://developer.amazon.com/docs/smapi/skill-manifest.html#permissions], and (events)[https://developer.amazon.com/docs/smapi/skill-manifest.html#events] which you can read about, but aren’t used yet in this project (if we do end up needing any of them I’ll describe them at that time).

models/en-US.json

The models/en-US.json file contains the Interaction Model ((Interaction Model Schema)[https://developer.amazon.com/docs/smapi/interaction-model-schema.html]) of the skill. The languageModel defines the interactions that Skill supports. The invocationName is the set of words that activates your skill. My Skill is for my church, Shepherd of the Valley, so I went with s.o.t.v. which will open my skill when you say something like, “Alexa, open S-O-T-V.”

Under the intents section are the intents your skill will respond to. I didn’t list all the built in ones, but they are AMAZON.CancelIntent, AMAZON.HelpIntent, and AMAZON.StopIntent. The first non-built-in intent my skill will support is the HelloIntent. The samples is an array of phrases also called utterances. These utterances are what will activate the intent for that skill. For example, “Alexa, tell S-O-T-V to say hello.”

{
  "interactionModel": {
    "languageModel": {
      "invocationName": "s.o.t.v.",
      "types": [],
      "intents": [
        {
          "name": "AMAZON.CancelIntent",
          "samples": []
        },
        ...
        {
          "name": "HelloIntent",
          "samples": [
            "hello",
            "say hello"
          ]
        }
      ]
    }
  }
}

That describes the definition of the skill. In the next post, I’ll walk through the supporting code.

I’m still a fan of AWS as I believe it is the best enabler of independent web development. You can complain about lock-in, but developers can create sophisticated applications using just the pay-per-use services and experiment with solutions without much up front cost.

One of the services that has received a lot of attention lately is Amazon Alexa. The voice service allows developers to create “skills” which extend the capabilites of Alexa and what it can respond to.

At the beginning of the summer my youngest daughter wanted to experiment with Alexa. She had the idea that she wanted to be able to ask it for puns and jokes. Of course Alexa already has those built in, but my daughter wanted specific puns and jokes that she likes. Summer came and is almost gone and with vacations, camps, and new jobs we didn’t get a chance to develop anything, but she still has the desire to build something.

As a geek dad I have to help her learn how to build this thing. So my learning and documenting project is to gain a deep enough understanding of Alexa Skill development to be able teach her hopefully during her Christmas break. I also hope to be able to package this into a course or book. To do this I will have to add more value than the typical AWS/Alexa Developer Console point and click tutorial.

I’m hoping to build something that is largely, if not completely, driven through the CLI. I also plan to dive deeply into the schema and interaction models. These are glossed over in all the tutorials I’ve seen, but from what I’ve learned so far, you can’t really understand what’s going on with a Skill unless you understand those things. Finally, I plan to show how to create an AWS CodePipeline that can auto-deploy the skill when changes are made and committed to a CodeCommit repository.

One of my biggest problems when I learn a new AWS service is that the vast majority of the tutorials give you an overview of the service via the AWS Console and leave you struggling as to how you would ever integrate it into an honest to goodness development cycle. As I learn and teach various aspects of AWS this will always be my focus.

The greatest source of satisfaction for me outside of my family is learning new things. This has made my choice to pursue a career in software development fortunate. In fact, a major source of discontent in a job is when I stop learning, but it also leads to the problem of turning a blind eye to organizational problems if I am learning.

I enjoy learning about software development so much that I’ve learned many languages and techniques that I have never and will never use in my job. I read a book on Ada in college and have never executed an actual line of it. I read a bunch of the Dylan documentation and even wrote some code for the simulator if I remember correctly. I’ve read the XP book and plenty of other methodology books and never worked in an organization that should have claimed it did anything but ad hoc software development.

Although the majority of my learning focus is on software development I also do a great deal of study in the area of personal development and one of the ideas I have run across is the difference between data and information. Data is just facts and figures while information is data that has context, meaning, and usefulness. I would consider the languages and methodologies I studied to be data. Since I haven’t actually put them in practice they aren’t any more useful than the dates of random historic events. I want to get in the habit of making what I learn useful; turn the data into information.

What I’m going to do is write (and possibly make videos) about what I’m learning. I’d like to turn this writing into a book or course of some sort. In my mind this would be the perfect combination of turning my love for learning into a source of income.


layout: post title: “Perils of a Family-First Software Developer” date: 2017-06-01 07:06:05 -0700 comments: false categories: [Career] — I’ve just survived a RIF, my skills and tool set are built around technologies that were modern 10 years ago, my interviewing skills have atrophied, and my aptitude on programming challenge web sites is poor. Oh crap! My career prospects look and feel bleak! :cold_sweat:

How I Got Here

I know I got myself into this situation. I traded a cutting edge career with uncertainty and unknowns for the stability, flexibility, and convenience of my current company. Job hopping and career focus would have kept my skills up-to-date and my job prospects brighter, but I knowingly sacrificed this aspect of my life to the benefit of my family.

Looking back there are things I should have done to mitigate this situation. There are the many side-projects I could have done instead of binging on some random Netflix show. There’s the business acumen I could have obtained if I had focused on building a company or product instead of playing a pointless video game. These aren’t mistakes I’m going to dwell on but things I want to learn from going forward.

Where I Am

I am employed! So I am thankful that God has continued to allow me the opportunity to provide for my family through this job. That being said, my long-term prospects at this company aren’t very good. The messaging around the Bay Area being a place where the company can’t compete for engineering talent points to strategy where it is likely it exits the area completely. My current role is to transfer my product knowledge to a team in Australia and then I will be rolled onto a team based on company need and my interests.

I have also taken some tepid steps to get myself into the job market. I even had a friend who started me through his company’s hiring process. This included a Hacker Rank test which I posted about earlier. To summarize, my current skill set did align well with this test. I also had a phone screen with the advertising team at Amazon, but the position they had was focused on devices.

Finally, the book Developer Hegemony before the RIF, has pushed me in the direction I always knew I should be going and that is away from being an exchangeable “resource” in the cog of a corporation.

The Path Out

I am currently clearing a little space so I have time to breath. At work I am being as helpful as I can to transfer knowledge to the new team and I have offered to travel if necessary. I also purchased Cracking the Coding Interview to better prepare myself for technical interviews. I now need to make myself a schedule for working through the book.

However, my main focus is on building my expertise in serverless development. I am thoroughly convinced that serverless will be dominant in the years to come and I plan to hitch my career to it. To that end, I’m going through Serverless Architectures on AWS and keeping up with all the AWS Lambda news I can find.

Lastly, I’m experimenting with ways to diversify my income streams. This blog is part of that experiment. I want to use it as a way to display my expertise and also to find ways to earn money through it so I purchased and am working through 10 Ways to Make Money from Your Blog. I probably have too many irons in the fire, but right now action, even if it is somewhat disjointed, seems like a better option than wallowing in what-ifs.

In this post you’ll see how to get the TypeScript portion of the project working. The setup mostly involves standard TypeScript setup and then a few AWS specific additions for the build and deploy steps.

TypeScript Configuration

The first thing to do is to get the application building locally.

tsconfig.json

{
  "compilerOptions": {
    "target": "ES5",
    "module": "commonjs",
    "noEmitOnError": true,
    "noImplicitAny": true,
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,
    "sourceMap": true
  }
}

This is pretty vanilla TypeScript configuration file. The target is ES5 and the module loader is commonjs.

gulpfile.js

var gulp = require('gulp');
var ts = require('gulp-typescript');
var path = require('path');
var sourcemaps = require('gulp-sourcemaps');

gulp.task('build:server', function() {
    var tsProject = ts.createProject(path.resolve('./tsconfig.json'));
    var tsResult = gulp.src([
        '**/*.ts',
        '!node_modules/**/*.ts'
    ])
        .pipe(sourcemaps.init())
        .pipe(tsProject())
    return tsResult.js
        .pipe(sourcemaps.write())
        .pipe(gulp.dest(path.resolve('.')))
});

gulp.task('build', ['build:server']);

gulp.task('default', ['build']);

I use gulp to build the TypeScript files and use the gulpfile.js to tell gulp which files to compile. Like the tsconfig.json, pretty standard stuff. I want to compile any *.ts files except those in node_modules.

npm setup commands

npm install gulp -g --save-dev
npm install gulp
npm install gulp-typescript --save-dev
npm install gulp-sourcemaps --save-dev
npm install typescript --save-dev

To be able to build using TypeScript you need to install several npm packages. The order doesn’t really matter, but first I install gulp (for reasons unknown to me I need to run with the -g –save-dev options and then do it again without any options). Next, I install gulp-typescript, gulp-sourcemaps, and typescript all with the –save-dev option because they are only needed to compile the TypeScript files and aren’t needed at runtime.

.gitignore

.DS_Store
node_modules
typings
**/*.js
npm-debug.log
!gulpfile.js

I added a .gitignore file to prevent git from tracking non-source files. Since this is a TypeScript project I actually don’t want to track any .js file thus the */.js. One exception is the gulpfile.js which leads to the !gulpfile.js

TypeScript Code

With the setup out of the way here is the actual code for the project.

index.ts

import * as awsServerlessExpress from 'aws-serverless-express'
import {ServerApp} from './serverApp' 
var serverApp = new ServerApp();
var server = awsServerlessExpress.createServer(serverApp.getApp());

exports.handler = (event: any, context: any) => awsServerlessExpress.proxy(server, event, context);

index.ts is the main entry point for the AWS Lambda function. aws-serverless-express needs to be imported and acts as the glue between the Express application and th Lambda function. The ServerApp module is imported and does the actual handling of requests; is is wrapped by aws-serverless-express by using the awsServerlessExpress.createServer() function call. Finally the AWS Lambda handler is exposed by the exports.handler assignment.

serverApp.ts

import * as express from 'express';

export class ServerApp {
    private app: express.Application;

    constructor() {
        this.app = express();

        this.configureApp();

        this.setRoutes();
    }

    private configureApp() {
    }

    public setRoutes() {
        this.app.get('/', function(req: express.Request, res: express.Response) {
            res.send({
                "Output": "Typescript Hello World!"
            });
        });

        this.app.post('/', function(req: express.Request, res: express.Response) {
            res.send({
                "Output": "Hello World!"
            });
        });
    }

    public getApp() {
        return this.app;
    }
}

ServerApp is a very basic Express application. The constructor has a call to configureApp() where future app configuration can occur, and it also makes a call to setRoutes() which will configure the routes for the application. This implementation of the routes is very basic for now just to get things up and running and to verify that the TypeScript code is being used and not the JavaScript from the template source.

npm express commands

npm install express --save
npm install --save @types/express
npm install aws-serverless-express --save
npm install --save @types/aws-serverless-express
gulp build

Now that we have the TypeScript code in place we need to add a few npm packages to get it to build. We need to install the express and aws-serverless-express modules and we need to install the corresponding TypeScript types. We can then run gulp build to compile the TypeScript files.

buildspec.yml

version: 0.1

phases:
  build:
    commands:
      - npm install
      - npm install gulp -g --save-dev
      - npm install gulp
      - npm install gulp-typescript --save-dev
      - npm install gulp-sourcemaps --save-dev
      - npm install typescript --save-dev
      - npm install express --save
      - npm install --save @types/express
      - npm install aws-serverless-express --save
      - npm install --save @types/aws-serverless-express
      - gulp build
      - aws cloudformation package --template template.yml --s3-bucket $S3_BUCKET --output-template template-export.json
artifacts:
  type: zip
  files:
    - template-export.json

To get this building in the CodeDeploy environment on AWS we need to update the buildspec.yml. We simply insert the same commands we used to setup the local environment to the buildspec.yml after the - npm install command.

Wrap Up

We now have a basic Express application written in TypeScript that is built and deployed on AWS. You are free to build your own application from this foundation. In future posts I will be adding functionality to this application which will include additional HTTP endpoints, connecting to an RDS instance, integrating with Auth0, and configuring the same application to be able to run locally to reduce the time needed for application development.