Home |  Lands End to John O Groats Unsupported |  Services |  Side Projects |  Posts (archive) |  Miles Davenport |  Career
lambda |  algorithms |  good devops |  bad devops |  hector
i'm so glad I chose this career |  the Konkan railway “Engineer message” |  Knowledge |  avoid |  RSS

Bad Design

Good design makes people want to use something

….or at the very least, is gives intuition the best chance of succeeding.

In other words, the phone rings, you know “what to do”, you pick it.

An old telephone had a single main function - to make and receive telephone calls :)

Fast-forward to today, and you have a versatile, rich, highly developed technology eco-system.

If you are a geek, male, and you live and breath technology, you are well catered for.

The fun starts when you don’t fall into this category.

Say you are an older person, and you feel that technology has passed you by.

Do you have any idea what sort of up-hill battle it will be to get that individual to “engage” (with technology)?

No, let’s stick with the young consumers. Oldies can wait. But hang on, wait a minute…

We will all be old some day, and I don’t want to be trapped by technology.

I want to be able to use technology in a familiar way, just like answering the telephone.

Let me ask you a question - how many older people (do you think) are lonely? Quite alot.

It would be amazing to do something about this. One major step would be to make tech easier to use.

It would allow people to use something like Skype easily. This is not my experience of a smart / mobile phone.

You are deluged by app updates. The user interface is over-complicated. The result is something which is not intuitive to an older person.

Technology does exist to help older people. But it often patronises, or makes “wrong” assumptions.

Technology should not assume the worst. An older person is not a child. The design of technology should not cater for the worst possible scenario.

The worst possible scenario is when you get an old persons alarm installed in your house…

And it’s red, and it has to be located in your lounge. The problems are numerous, but include the colour, yes it’s red, and it shouts “I am a red alarm in your lounge.”

The person (and this is important) doesn’t want to have a sodding red alarm in their front room.

Why can modern technology not learn about good design, usability, kiss (keep it simple….).

If we started adopting these principles, then the hill, I mentioned previously, would be less of a climb, and the lonely people may not be as lonely.

Imagine what it would be like to have smart technology which is easy to use, benefitting, not patronising, but helping people.

It would be amazing.

To make this happen, it’s time that reliability, design, function, and simplicity were applied to technology.

I want this to happen.

»


The "Out of Order Bathroom, and Why You Should Care, "regardless......"

That’s fine….. Why should I….. It’s got nothing to do with me…..

Or has it….got something to do with you?

Today has been really frustrating. I had a great afternoon with friends, but the return journey home on the train was not great.

To put it bluntly, I had eaten something which hadn’t agreed with me, and I needed the bathroom badly :(

I arrived at Stevenage station, and the bathrooms were all out of order. A twenty minute wait for the train, and I was uncomfortable.

The train toilet was out of order. I had to wait in agony.

Thirty minutes later, I managed to end the discomfort, and started to feel better.

This got me thinking.

There is the most basic human need to be able to use a clean bathroom. It would appear that the UK national rail operator doesn’t understand this basic need.

It doesn’t stop there. I am a healthy male in his forties, who was uncomfortable. What about if you are a mother, with children, or an elderly gentleman?

don't care

There is an acceptance, where people do just that - accept it. I have always disliked apathy, and the associated “it’s got nothing to do with me.”

Well, it has got something to do with you. Because if we all didn’t bother, where would we be?

“Yes you heard. You should care.”

I’m not just referring to bathrooms, but anything.

It’s not fashionable to care. It’s far easier to say “nothing to do with me”.

But regardless of what you do, you should care.

Because the smallest change is worth it.

Try it:

Improving things is infectious

Sharing knowledge

Self-service and self-sufficiency

Look for solutions

Includes impromptu plumbing :)

It’s important that people do care, and take responsibility.

»


Debugging Java 8 Streams

The peek() method is useful for debugging Java 8 stream(s).

This example doesn’t need an explicit peek(), but it shows how useful the peek method is for debugging:

package com.chocksaway;

import java.util.List;
import java.util.stream.Collectors;

/**
 * Author milesd on 31/12/2017.
 */
public class FilterNumbers {
    private List<Integer> numberList;

    public FilterNumbers(List<Integer> numberList) {
        this.numberList = numberList;
    }

    public List<Integer> process() {
        return numberList.stream()
            .filter(each -> each > 15)

            // peek for the first filter
            .peek(each -> System.out.println("Debug 001:\t " + each))

            .filter(each -> each % 3 == 0)

            // peek for the second filter
            .peek(each -> System.out.println("Debug 002:\t " + each))

            .collect(Collectors.toList());
    }
}
Corresponding Unit Test:
import com.chocksaway.FilterNumbers;
import org.junit.Test;

import java.util.ArrayList;
import java.util.List;

import static junit.framework.TestCase.assertTrue;

/**
 * Author milesd on 31/12/2017.
 */
public class TestFilterNumbers {
    @Test
    public void peekAtLambda() {
        List<Integer> numbers = new ArrayList<>(List.of(12, 13, 14, 15, 20, 21, 24));
        FilterNumbers filterGreaterFifteenDivisibleByThree = new FilterNumbers(numbers);

        List<Integer> result = filterGreaterFifteenDivisibleByThree.process();

        assertTrue(result.contains(21));
        assertTrue(result.contains(24));
    }
}
Running the Unit Test

The debug output:

Debug 001:	 20
Debug 001:	 21
Debug 002:	 21
Debug 001:	 24
Debug 002:	 24

peek() shows the Debug 001, and Debug 002 for the first and second filter second statements.

»


Node and AWS API Gateway

Happy New Year :D

You would think that integrating a call from a Node app into an AWS API Gateway would be fairly easy.

It wasn’t.

A number of things prevented me from working efficiently:

  • Context switching - I need time to learn, play, gain expertise, fine-tune, and pass on the knowledge.

    This hasn’t happened. The constant problems with a third-party platform prevent this focus on a single task.

  • Different / later version of Node (which use things like async)

  • Not being able to develop locally.

  • Not having the IAM roles / permissions to work.

Over the break, I wanted to move forward, and break-the-back of this task

I went back to basics, and grabbed my notes from the February 2017 meetup, where I had presented on using the AWS API Gateway.

Miles Davenport

I used the sample PetStore (provided by the API Gateway), and created an API key, and IAM Role which was associated to the PetStore, and Usage plan

I started off by using just the API key to test an endpoint with:

GET /int//pets/1 HTTP/1.1
Content-Type: application/json
x-api-key: [snip]
Host: [snip]
Connection: close
User-Agent: Paw/3.1.4 (Macintosh; OS X/10.13.2) GCDHTTPRequest


The response is here:

HTTP/1.1 200 OK
Date: Sun, 31 Dec 2017 16:12:33 GMT
Content-Type: application/json
Content-Length: 49
Connection: close
x-amzn-RequestId: [snip]
Access-Control-Allow-Origin: *
X-Amzn-Trace-Id: Root= [snip]

{
  "id": 1,
  "type": "dog",
  "price": 249.99
}

Integrating with Node

The next step was integrating with Node v6.10.3.

I wanted to use https://www.npmjs.com/package/aws-api-gateway-client.

I have developed the following simple Node app, which allows me to call the PetStore endpoint successfully:

const express = require('express');
const app = express();
const crontab = require('node-crontab');
const apiEndpoint = '[snip]';
const APIGatewayClientFactory = require('aws-api-gateway-client').default;

let AWS = require('aws-sdk');
let sts = new AWS.STS();

let params = {};
let AWSCredentials;

let data = {};


function updateEC2CredentialsViaCronjobEveryMinute() {
    crontab.scheduleJob("* * * * *", function() {
        getEC2SessionCredentials()
            .then((credentials) => {
                AWSCredentials = credentials;
            })
            .catch((err) => {
                console.log(err);
            });
    });
}


function getAPIGatewayWrapper(AWSCredentials, params, pathTemplate){
    return APIGatewayClientFactory.newClient({
        invokeUrl: apiEndpoint,
        accessKey: AWSCredentials.Credentials.AccessKeyId,
        secretKey: AWSCredentials.Credentials.SecretAccessKey,
        sessionToken: AWSCredentials.Credentials.SessionToken,
        region: 'eu-west-1',
        apiKey: '[snip]'
    }).invokeApi(params, pathTemplate, 'GET', {}, {})
}


function getEC2SessionCredentials() {
    console.log("getting creds");
    let promise = new Promise((resolve,reject)=>{
        data = sts.getSessionToken(params, function (err, data) {
            if (err)
                reject(err);
            else
                resolve(data);
        })
    });

    return promise;
}


app.get('/', (req, res) => {
    let params = {
        number: '1'
    };

    let pathTemplate = '/pets/{number}';

    getAPIGatewayWrapper(AWSCredentials, params, pathTemplate, res)
    .then((APIGatewayResponse) => {
        data = APIGatewayResponse.data;
        console.log(JSON.stringify(APIGatewayResponse.data.type, null, 4));
        res.status(200).send(data);
    })

    .catch((err)=>{
        console.log(err);
        data = {
                    "error": "an error occurred"
                };
        res.status(500).send(data);
    });

});

getEC2SessionCredentials()
.then((credentials) => {
    AWSCredentials = credentials;
    updateEC2CredentialsViaCronjobEveryMinute();
    app.listen(3000, () => console.log("starting"));
});

I have been experimenting with updating the session AWS credentials (used by the aws-api-gateway-client), and have opted for a Cronjob.

Running with curl gives me the output I am expecting:

http://localhost:3000/?14 --> <stdout>
--_curl_--http://localhost:3000/?14
{"id":1,"type":"dog","price":249.99}

What have I learnt?

The process of implementing my own API gateway, and local Node app has allowed me:

  • To concentrate on the task at hand.

  • Used my own AWS account, my own API keys, and my own IAM roles.

  • Completed a working POC, which has reinforced learning, by staying on track.

  • The code can be further improved, but has allowed me to gain more experience in Node..

What I have avoided?

  • Getting involved in hacking AWS IAM roles.

  • Losing focus.

  • Remote development on an EC2 box.

What I haven’t avoided?

  • Interesting…yes, but spending my own time working on a “work task”

I’ve deliberately gone back to basics over the holidays, kept things simple, and focused, and surprise surprise, things have gone to plan.

»