Saturday, November 17, 2018

Things that are hard: trivial POST request from the browser

I'm trying to make a trivial web app. Why is this so hard?

Glitch is an amazing site for making this, but its "simple node app" example does not POST anything back to the server.

I finally got this working. Here's the result -- it might be useful to you to remix it.

https://send-json-post.glitch.me

Things I figured out:
  • add the json middleware to express
  • some library to post from the client. I used axios because it's what we use in our apps. This is probably not the simplest one
  • browserify middleware to be able to install it from the client
  • the Chrome developer tools, alt-cmd-I on a mac:
  • you can see the request headers in the network tab if you click on the request of interest and then scroll down in the right place.
  • to play with things in the console, like trying to make a POST request: find the script under "sources". put a debug point where you need access (like in my case, I needed axios, so I put it at a place where I used it). Then in the "scope" section of the debugger, find that variable, right-click on it, and save as global. It appears as "temp1" in your console. Don't forget to push play to make the debugger let go. The global variable stays available and you can call "temp1.post(...)" etc to figure out what you're doing.

Then getting anything to update in the front end, that was hard too. I'm definitely going to bring in a front end framework before I try to do anything further.

Friday, July 27, 2018

Do Things Right with TypeScript

A collection of pointers for the present and future.

Print the whole error


`tsc --noErrorTruncation`

Why tsconfig.json is hard


tsconfig.json is important, because the TS compiler does way more, way more flexibly, than the Java compiler does. It's both a transpiler and a typechecker.

What kind of JS do you want outputted? Choose your level of ECMAScript compatibility (as ancient as ES3 or as modern as ESnext) and also your module system compatibility (commonjs, amd, or several more).

What will be magically be available in your runtime? Bring in the type declarations for these things (such as the DOM) with the `"lib": ["DOM"]` compiler option, or in `"types": ["@types/node"]` (node module globals like `__filename`, or node built-ins like `fs`).

Also choose how stringent the typechecking is, with "strict" and its various suboptions.

Choose where your input files are, and where your output files go.

Choose what to output: only JS? sourcemaps? type declarations? type declaration maps?  ... and for those maps, choose relative paths to the source.

The good news is: even if compilation has errors, tsc will output JS. So you can test even when tricky compile errors that you can't figure out plague you.

Iterate through objects and arrays


There exists both `for (const a of array)` and a similar construct which shall not be named but contains the work `in` instead of `of`. Do not use that one.

To iterate through an array: for (const a of array) { ... }

... ok I can't stand it anymore I'm moving this post to Medium. Google clearly does not care about this platform, it may go away like Google Reader, and it is super painful to put code here.

https://medium.com/@jessitron/do-things-right-with-typescript-7a3ad7371387

Wednesday, July 25, 2018

Do Things Right with npm install

Lately I've been wrestling with npm. Here are some rules I've learned:

Use `npm ci` rather than `npm install`

`npm ci` will bring down exactly the dependencies specified in package-lock.json. `npm install` does more than that; it also tries to update some libraries to a more recent version. Sometimes it updates URLs or nonsense in package.json so that it my `git status` is dirty. Sometimes it does deduping. Sometimes it sticks the version you have lying around. I haven't figured it out. It seems to be pretty dependent on the current circumstances on my file system.

Now I only use `npm install` if I specifically want to change the dependencies in my filesystem.

Use `npm install --save-exact`

Especially for snapshots. Semver does not work for snapshots or branches or anything but releases. And npm only works with semver. If you are not using a release; if you publish with build tags or branch tags or anything like that; do not give npm any sort of flexibility. It will not work. Specify a precise version or else it will give you nasty surprises, like deciding some alphabetically-later branch is better than the master-branch version you specified.

Use `npm view` to check the status of a library

This is quite useful. Try `npm view <lib-name>` and it brings to your command line the info you can get from the npm website. You can ask it for specific fields. To get the latest version of chalk:

$ npm view chalk dist-tags.latest
2.4.1


If you want to do anything programmatic with this info, the "do things right" flag for `npm view` is `--json`.

Try `npm ls` but then dig around on the filesystem

Exploring the dependency tree, `npm ls` is really cool; it shows it to you. You can see where you're getting a specific library with `npm ls <lib-name>` except that it doesn't always work. In the end, I dig around in my node_modules directory, using `find -name <lib-name> .` to look for the real thing.

Other times I use my little node-dependency dungeon explorer game to see what version of stuff is where. 

These are just a few of the nasty surprises I've found moving from Java to TypeScript, from maven dependencies to npm. Dependency management is an unsolved problem, and the people working on npm have made huge improvements in the last few years. I look forward to more.

Sunday, April 15, 2018

Horizonal goals

Video version here

There's this great, short book by John Kay called Obliquity. It's about goals that you can't achieve by aiming for them directly; you have to look for an oblique goal that will happen to get you there. Like, you can't aim for "happiness;" you have to find something such that aiming for it makes you happy, like raising children or writing or helping people who are hurting.

This book gives a name to some parts of my seamaps. The star at the top is the "high-level objective," the unquantifiable goal which can never be achieved. Aiming for it sends us in a direction which happens to obliquely fill a goal such as "happiness" or "profit." Goals such as "change the way development is done" or "find the optimal combination of music and words" or "address the observability needs of modern architectures" These are horizonal goals; as we make progress, the state of the art moves. We can never reach the horizon, but aiming for it takes us interesting places.

at the top, a star called "high-level objective." Below that, the sea. In the sea, a big island with a snowcapped mountain, called "Goal." Below that, a smaller island called "subgoal." Below that, a whirlpool called "necessary state" and a sailboat with oars and people, called "action."

The mountains in the seamap are milestones. They're achievable, measurable goals that we work toward because they're in the direction of our high-level objective. Periodically we climb up and look around, take stock of whether our current direction is still going toward our star, and if not, change our milestone goals.

There are many smaller milestones on the way to the bigger one. Each offers an opportunity to take stock and possibly shift direction. There are actions that we take to move toward these goals. This is us in the boat, rowing.

Obliquity adds another element: necessary states. A necessary state to moving toward the next feature is: tests are passing. A necessary state for teamwork is that we are getting along with each other. Many of the actions we take are aimed at maintaining or restoring necessary states. These are like the whirlpools in my seamap; we have to smooth them out before we can row in the direction of our choice.

For example, here is a seamap for my current activity:

high-level objective: change the way people think about programming. Goal: explain Symmathecist. Subgoal: explain Horizonal. Necessary state: don't be too drunk. Action: type this post before opening wine.  

I will now hit "publish" and go open a bottle of wine.

Sunday, December 17, 2017

a reference to Deference

I'm writing more over at Medium these days: https://medium.com/@jessitron/deference-or-collaboration-pick-one-13ab798f3192

Tuesday, October 24, 2017

Reference: Typescript asynchronous sleep that returns a promise

I want some code to execute after a delay. I want to do this with promises, in TypeScript, asynchronously. Apparently this is hard. Here is the spell:

const sleepPlease: (number) => Promise<void>
    promisify( (a, b) => setTimeout(b, a));

const slow: Promise<string> = 

    sleepPlease(500).then(() => "yay finally");

I imported promisify from "util". setTimeout is built in, but its arguments are in the wrong order to naturally pass to promisify

Tuesday, July 18, 2017

Dictionary Objects in JavaScript and TypeScript

TL;DR: when using an object as a dictionary in TypeScript/ES6, iterate through it using `Object.keys()`.

Coming from statically typed languages, I keep looking for a Map or Dict type in TypeScript (or JavaScript). People use objects for this, though. Objects have key-value pairs in them, and you can add them and delete them and declare them statically and it looks nice, especially in literals.

const dictionary = { 
   impute: "attribute to",
   weft: "the holding-still strings on a loom",
}

But using a JavaScript object as a dictionary has its quirks.

There are three ways to iterate through the values in the object. (This is TypeScript syntax.)

Flip through the enumerable keys defined on an object:

for (const key of Object.keys(dictionary)) {
   const valuedictionary[key]
   console.log(`${key} -> ${value}`)
}

This one makes the most sense to me; it's what I expect from a dictionary. It flips through the values in an array of the keys defined on that object directly, no prototypal inheritance considered. This is how JSON.stringify() prints your object.

Flip through the enumerable keys defined on that object and its prototype chain:

for (const key in dictionary{
   const value = dictionary[key]
   console.log(`${key} -> ${value}`)
}

This is the easiest one to write. It flips through the keys defined on the object and its prototype chain. If you're using an ordinary object for this, and no one has done anything bizarre like add an enumerable property to Object, it's fine. tslint hates it though; it bugs me about "for(...in...) statements must be filtered with an if statement." tslint is like "OMG, you do not know what is on that thing's prototype chain it could be ANYTHING"

I find it backwards that for(...in...) flips through property names of an object, while for(...of...) flips through values in an array. This confuses me daily in TypeScript. If you accidentally use for(...of...) instead of for(...in...) on an object, then you'll see 0 iterations of your loop. Very sneaky. If you accidentally use for(...in...) on an array, you get the indices instead of the values, also confusing. TypeScript and tslint don't warn about either error, as far as I can tell. :-(

Flip through the enumerable and non-enumerable keys defined on that object:

for (const key of Object.getOwnPropertyNames(dictionary)) {
   const value = dictionary[key]
   console.log(`${key} -> ${value}`)
}

This one flips through only keys on the object, not its prototype chain, and also gives you the names of non-enumerable properties. You probably don't want those.

What are non-enumerable properties?

Conceptually, they're properties that don't make sense to flip through, that we don't want JSON.stringify() to look at. They're hidden from for(...in...) iteration and from Object.keys(). You can still access them on the object. For instance, constructors of TypeScript classes are non-enumerable properties. Methods on built-in types like Array and object are non-enumerable. They stay out of the way.

When would we want to flip through them, like in Object.getOwnPropertyNames()?
I don't know, maybe for debugging.

Why make a non-enumerable property?
I hit a use case for this today: serializing an instance of a class with recursive fields. JSON.stringify() can't print recursive structures.

Side quest: Making recursive objects printable

In TypeScript, every field in a class instance (including any inherited field) is an enumerable property, returned from Object.keys() and printed by JSON.stringify(). See this TreeNode class that tracks its children, and its children track it:

class TreeNode {


private _parent: TreeNode;
public children: TreeNode[] = [];


public constructor(public readonly value: string) {
}
...
}

Printing an instance of TreeNode gives me: `TypeError: Converting circular structure to JSON` waah :-(

Here's a tricky way to say "Hey JavaScript, don't print that _parent field". Explicitly override its enumerable-ness in the constructor.


class
TreeNode {

private _parent: TreeNode;
public children: TreeNode[] = [];

public constructor(public readonly value: string) {
Object.defineProperty(this, "_parent", { enumerable: false });
}
...
}


We can get tricky with TypeScript class fields. After all, they get tricky with us.

Properties on a class instance

In TypeScript, class instance fields show up in Object.keys() and accessor-based properties (like with getters and setters) do not. They're properties on the prototype, which is the class itself. So if you want to see accessor properties, use for(...in...) on class instances. That gets the enumerable properties from the prototype chain. Watch out: these include methods.

Why iterate through the properties on a class? I don't know, maybe for debugging again. If you do it, I suggest skipping methods. This makes tslint happy because its an if statement:

for (const propertyName in classInstance) {
  if (typeof classInstance[propertyName] !== "function") {
    console.log(`${propertyName}=${classInstance[propertyName]}`);
  }
}

Recommendations

If you have a class instance, access its properties with dot notation, like treeNode.children. That way TypeScript can help you avoid mistakes. If you have a dictionary object, access its properties with index notation, like dictionary["impute"] (and turn off the angry tslint rule). Class instances have specific types; dictionary objects are type object. Access the contents of a dictionary using Object.keys().