Tuesday, March 12, 2019

Open Source needs Open Source companies.

The other day, AWS announced its latest plans to work around the license of ElasticSearch, a very useful open source project cared for by Elastic.

"At AWS, we believe that maintainers of an open source project have a responsibility to ensure that the primary open source distribution... does not advantage any one company over another. "

Can I call BS on this?

I mean, I'm sure AWS does believe that, because it's in their interest. But not because it's true.

Great pieces of software are not made of code alone. They're made of code, which is alive in the mental models of people, who deeply understand this software and its place in the wider world. These people can change the software, keep it working, keep it safe, keep it relevant, and grow it as the growing world needs.

These people aren't part-time, volunteer hobbyists. They're dedicated to this project, not to a megacorporation. And they eat, and they have healthcare.

Reusable software is not made of code alone. It includes careful APIs, with documentation, and of communication lines. The wider world has to hear about the software, understand its purpose, and then contribute feedback about problems and needs. These essential lines of communication are known as marketing, developer relations, sales, and customer service.

Useful software comes out of a healthy sociotechnical system. It comes out of a company.

If a scrappy, dedicated company like Elastic has a license that leans customers toward paying for the services that keep ElasticSearch growing, secure, and relevant -- great! This benefits everyone.

Poor AWS, complaining that it doesn't have quite enough advantages over smaller, specialized software companies.

Then the next sentence: "This was part of the promise the maintainer made when they gained developers’ trust to adopt the software." Leaving aside the BS that a person who gives away software owes anyone anything --

The best thing a maintainer can do for the future of all the adopters is to keep the software healthy. That means watching over the sociotechnical system, and that means building a company around it. A giant company fighting against that is not on the side of open source.

Sunday, December 30, 2018

CSS Positioning: a summary

I've been frustrated every time I try to grasp CSS for years. "I just want this on the left and this to be over here!" etc. Now I realize that CSS doesn't work that way for very good reasons. In most programming, we give instructions for what we want to happen. But in CSS, it's more like we are describing a situation -- relationships -- and then letting the browser figure it out. That's because the browser has to handle many different circumstances. Resolutions, interfaces, font sizes. I describe how the parts go together, it figures out how to put them on the screen.

When I get upset about the properties for one part being dependent on the properties of its parent containers and siblings, it's OK Jess: remember that CSS is about interrelationships, so this is normal.

Having got that, I'm now able to learn about how to put things on the screen without yelling in frustration and confusion.

So far, I've looked up the position property and learned that it doesn't do much. There are other ones like display that seem more important. But meanwhile here's my executive summary:

The position property determines two things: whether the element participates in document flow, and what the properties top bottom left right do. These are the useful ones:

position: static - the default. Stay in document flow; top bottom left right do nothing.

position: relative - nudge. Stay in document flow.  top bottom left right nudge the element in that direction from where it would have been. This also has some effect on child element positioning, at least in the case of ::before pseudo-elements (weird CSS tricks).

position: absolute - override. Remove the element from document flow. top bottom left right tell it where exactly where to be within the document (or within the next absolutely-positioned element up the tree).

position: fixed - override and hold weirdly still. Remove the element from document flow
tell it exactly where to be within the viewport. That means within the browser window (or the iframe if it's in one). When the page scrolls, this element stays in the same place. People use this for menus.

Please lmk if you have corrections.

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