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.

In this post I’ll review the files that CodeStar creates for a default project. The process of starting a project is fairly simple, but if you want a walkthrough you can go to the first post in this series.

If my understanding is deficient in any area below, please let me know so I can update this post.

Source Code & Infrastructure

When the project is created, not only is the source code created, it is also put into CodeCommit for source control. Additional CodeBuild and CodeDeploy projects are created to do the build and deploy respectively (they did a good job of naming :+1:).

app.js

var express = require('express');
var app = express();

app.get('/', function(req, res) {
  res.send({
    "Output": "Hello World!"
  });
});

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


// Export your Express configuration so that it can be consumed by the Lambda handler
module.exports = app

This code sets up the Express app and sets it to respond to GET and POST requests.

buildspec.yml

version: 0.1

phases:
  build:
    commands:
      - npm install
      - aws cloudformation package --template template.yml --s3-bucket $S3_BUCKET --output-template template-export.json
artifacts:
  type: zip
  files:
    - template-export.json

The buildspec.yml file is used by CodeBuild to package the local environment into the deployable artifact. My understanding is that the source code from CodeCommit is copied into the environment, then any commands you run add to the environment, and this environment is packaged as an artifact, a .zip file in this case.

In the build phase the ‘npm install’ command is run to setup the npm environment. The ‘aws cloudformation package’ command takes template.yml (described below) and generates a CloudFormation template.

The artifacts phase declares where to find the files included in the output of the build. The ‘files’ declaration says to grab the template that was created with the ‘aws cloudformation package’ command. I’m assuming the type: zip declaration is something special that says to zip the environment because it the source is never explicitly defined.

index.js

 'use strict';
  
  const awsServerlessExpress = require('aws-serverless-express')
  const app = require('./app')
  const server = awsServerlessExpress.createServer(app)
  
  exports.handler = (event, context) => awsServerlessExpress.proxy(server, event, context);

This code initializes the app that will be referenced by the Lambda function defined in template.yml (described below). It only exports the function handler but the definitions of what is handled happens in template.yml and the handling happens in app.js.

package.json

{
    "name": "express-HelloWorld",
    "description": "Hello World ExpressJS WebService",
    "version": "0.0.1",
    "private": true,
    "dependencies": {
        "express": "latest",
        "aws-serverless-express": "latest"
    }
}

The package.json describes the project and includes the dependencies of the npm application. In this case ‘express’ and ‘aws-serverless-express’ are needed to run the project.

README.md

There is a README file that should be updated to describe the application.

template.yml

 AWSTemplateFormatVersion: 2010-09-09
  Transform:
  - AWS::Serverless-2016-10-31
  - AWS::CodeStar
  
  Parameters:
    ProjectId:
      Type: String
      Description: AWS CodeStar projectID used to associate new resources to team members
  
  Resources:
    HelloWorld:
      Type: AWS::Serverless::Function
      Properties:
        Handler: index.handler
        Runtime: nodejs4.3
        Role:
          Fn::ImportValue:
            !Join ['-', [!Ref 'ProjectId', !Ref 'AWS::Region', 'LambdaTrustRole']]
        Events:
          GetEvent:
            Type: Api
            Properties:
              Path: /
              Method: get
          PostEvent:
            Type: Api
            Properties:
              Path: /
              Method: post

This is a Serverless Application Model (SAM) template which is template specifically designed to describe Lambda functions so they can be deployed by CloudFormation. It describes the Resource (a Lambda function), the Handler (index.handler from index.js), the Runtime (nodejs4.3), and the Events setup API Gateway to respond to HTTP events (GET and POST in this case).

Those are the defaults which are pretty straightforward. Please email me at brian@yamabe.net or tweet me @brian_yamabe. Next time I’ll add support for using TypeScript.

This will be a multi-part series on using TypeScript in an AWS CodeStar project. I don’t have the writing stamina or ability to put this all in one post. Heck, I don’t know how much I will get into each post, but I will work through what I’ve learned about getting started with on this path.

For background, I did an experiment where I implemented a Restful service with Node-TypeScript-Express, Ruby-Sinatra, Python-Flask, and Java-Jersey. You can see these over on GitHub and yes I will eventually do a writeup of my thoughts on the experiment. I was about to do another implementation of the service using AWS Lambda and Python (which feels like the most natural fit in my opinion) when AWS CodeStar was announced. I did a little poking around and found a template for creating an Express project and decided that since I enjoyed developing the Node-TypeScript-Express version of the service the most, I would use this Express template and see if I could get TypeScript to work and then make the effort to port the Node-TypeScript-Express to a CodeStar project.

Baby Steps

The first step was getting starting the project which was as simple as clicking “Start a project.” CodeStar Start

Then choosing to start an Express.js Lambda project: Express Project

After naming the project Express Project

and getting information on the CodeCommit repository that was setup Express Project

I got to the project dashboard that gives the status of the build and waited for the project to build and deploy Express Project

and then clicked on the “Application endpoint” to verify the build. Express Project

The next post will focus on the template code the CodeStar project created for us. If you have any questions or think that some aspect needs further explanation, contact me at brian@yamabe.net or brian_yamabe on Twitter.

I have been using Hacker Rank for a month or so to get a feel for it. I know that some companies use it as part of their interview process so it seemed like a good idea to get familiar with it.

I like the site and think the problems are fair, challenging, and can help you to hone your development skills. That being said, a friend had me go through their version of the test they give as part of their interviewing process. I stunk at it. The problem was the timed nature of the process. When solving a Hacker Rank problem in the context of using the regular site, you can explore options, refine your code and algorithms, and have the opportunity to change directions if you start down the wrong path. In the timed interview, this just doesn’t work. I went down the wrong path on the first problem and never really recovered. It wasn’t that the problem was hard, I eventually solved it, it’s just that I thought I could do it using one data structure and then when that wasn’t working I switched to another. That just put added time pressure on the rest of the problems and I made a bad assumption on another problem that pretty much sunk the rest of my “interview.”

I understand, if not like, the need to look for a baseline of programming ability, but feel like tests like these don’t mimic a work environment in a meaningful way that reflects any candidates ability to do the job.

What this and Developer Hegemony highlight to me is the very real need to make myself something other than a “corporate resource.”