10月20日にメジャーアップデートとしてリリースされたNode.js v15の紹介

こんにちは@watildeです。Node.jsでは、主にWHATWG/URLあたりの実装を担当しています。

今回は、2020年10月20日に新しいメジャーアップデートとしてリリースされたv15の変更点のうち、筆者が気になった代表的なものについて紹介します。全てはカバーできていないので、下記にて他の方の解説記事が出たら随時リンクを追加してブログ記事をrequire()していきます。

各変更の紹介では、なるべく参考リンクを付けているので詳細が気になった際はリンクから一次情報に飛んで読んでみてください。また、情報に誤りがあった場合はTwitterにて教えていただけると助かります。

背景

Node.jsは半年に一度メジャーアップデートを実施しており、4月は偶数のバージョン、10月は奇数のバージョンをリリースすることになっています。新しい奇数のバージョンのリリースが行われると、追いかけるように一つ前にリリースされた偶数のバージョンLTSに移行します。

参考: https://github.com/nodejs/Release#release-plan

今回のケースでは、2020年10月27日にv14がLTSを開始し、2021年10月19日まではfeatureなどもマージされるアクティブLTSに、以降から2023年04月30日まではクリティカルなバグの修正のみを行うメンテナンスLTSへと移行します。

参考: https://github.com/nodejs/Release#release-phases

リリース内容の詳細は、下記のリリースノートと公式ブログのアナウンスにて紹介されています。

参考:

代表的な変更の紹介

deps: npm v7の導入

npmのv7が同梱されました。新機能としてWorkspaceやacceptDependenciesなどが使えるようになり、Monorepoでの開発が捗るようになります。詳細は下記の参考リンクにて。

参考: https://blog.watilde.com/2020/10/14/npm-v7%e3%81%ae%e4%b8%bb%e3%81%aa%e5%a4%89%e6%9b%b4%e7%82%b9%e3%81%be%e3%81%a8%e3%82%81/

process: unhandledRejectionがエラーをthrowするようになる

この変更については、@kimamulaさんが書いた記事が詳細に解説しているので、下記にリンクを貼っておきます。

参考: https://zenn.dev/kimamula/articles/b32d11d52c2b7a733119

ここではコード例を元に簡単に紹介します。

v14以前

Node.js側でハンドリングがなされていないエラーを、UnhandledPromiseRejectionWarningやunhandledRejectionイベントで処理していました。

$  node -p "Promise.reject()"
Promise { <rejected> undefined }
(node:29606) UnhandledPromiseRejectionWarning: undefined
(node:29606) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:29606) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

しかし、これはそもそも想定外のエラーが発生したということなので、プロセスをエラーで終了するべきだと議論が長きに渡ってなされていました。

参考: https://github.com/nodejs/node/issues/830

v15以降

そして今回のv15では、プロセスをエラーとして終了する変更が行われました。

$ node -p "Promise.reject()"
Promise { <rejected> undefined }
node:internal/process/promises:218
          triggerUncaughtException(err, true /* fromPromise */);
          ^
[UnhandledPromiseRejection: This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). The promise rejected with the reason "undefined".] {
  code: 'ERR_UNHANDLED_REJECTION'

これでデフォルトの挙動は変更されましたが、以前の挙動に戻したい場合は--unhandled-rejections=warnオプションを渡すことで可能です。

参考: https://github.com/nodejs/node/pull/33021

quic: QUICの実験的サポート

QUICとは、UDP上で動作するトランスポートプロトコルで、TLS 1.3を介した組み込みのセキュリティ向上、フロー制御、接続移行、多重化などが含まれています。詳しくは@flano_yukiさんの書いたHTTP/3の解説を参照。

参考: https://asnokaze.hatenablog.com/entry/2020/06/01/005625

QUICは、netモジュール内で実装されており。--experimental-quicオプションを渡すことで利用することができます。

const { createQuicSocket } = require('net');

詳細な使い方に関しては、@nwtgckさんが記事にて良いログを残されているので紹介させていただきます。

参考: https://scrapbox.io/nwtgck/Node.js%E3%81%AEQUIC%E3%82%92%E5%85%88%E5%8F%96%E3%82%8A%E3%81%97%E3%81%A6%E4%BD%BF%E3%81%A3%E3%81%A6%E3%81%BF%E3%82%88%E3%81%86

追記(2020/10/27)

@lekoさんが詳細な記事を書いてたので、追加でリンクをこちらに貼ります。

参考: https://blog.leko.jp/post/http-over-quic-on-nodejs15/

参考: https://github.com/nodejs/node/pull/32379

deps: V8エンジンのバージョンがv8.6に更新

下記の4つの構文が利用可能となりました。それぞれの詳細については参考リンクを貼っておきます。

  • Promise.any()
  • エラー集約: AggregateError
  • 文字列の一括置換: String.prototype.replaceAll()
  • 論理代入演算子: &&=||=, ??=

ここでは、コード例を元に利用頻度の高そうなPromise.anyについて簡単に紹介します。

Promise.anyは、与えられた複数のプロミスを実行し、1つでも実行が正常に完了されるまで行われるまで実行されます。似た挙動をするPromise.raceでは、処理の完了・エラーの発生に関わらず、最初に処理が終わった時点で終了するところが違います。

// Code from https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Promise/any
const pErr = new Promise((resolve, reject) => {
  reject("Always fails");
});
const pSlow = new Promise((resolve, reject) => {
  setTimeout(resolve, 500, "Done eventually");
});
const pFast = new Promise((resolve, reject) => {
  setTimeout(resolve, 100, "Done quick");
});
Promise.any([pErr, pSlow, pFast]).then((value) => {
  console.log(value);
})
// 出力内容: "Done quick"
Promise.race([pErr, pSlow, pFast]).then((value) => {
  console.log(value);
})
// 出力内容: "Always fails"

参考:

timer: timers/promisesの実験的導入

setTimeoutsetImmediateのプロミスAPIが実験的に実装されました。WHATWG側では議論中のものが、Node.jsが先行してリリースという形になります。今後、様子見しながらステージを上げていくことになるかと思います。

参考: https://github.com/whatwg/html/issues/617

呼び出しはtimers/promises内にあり、使い方としては以下の通りになります。

const {
  setTimeout,
  setImmediate
} = require('timers/promises');
setTimeout(10, null, { ref: false })
  .then(console.log);
setImmediate(null, { ref: false })
  .then(console.log);

参考: https://github.com/nodejs/node/pull/33950

lib: EventTarget関連のインターフェースのグローバル化

下記のモジュールがWeb APIと互換性を持った形でグローバル化されました。開発者・利用者が重なっているからか、ブラウザと挙動が近づきつつありますね。

  • Event
  • EventTarget
  • MessagePort
  • MessageChannel
  • MessageEvent

参考:

url: URLの仕様追随

こちらもWeb API互換性の話。WHATWG/URLでは日々URLのフォーマットについて仕様が更新されていますが、最近はいくつかの破壊的変更が仕様側で発生したので、v15にて更新を追随されたものがリリースされています。

参考: https://github.com/nodejs/node/pull/35477

dns/promisesの追加

日本のCore collaboratorの@shisama_さんのコミット。紹介記事がどこかで出るのかなと思うので一旦待ち。

参考: https://github.com/nodejs/node/pull/32953

余談

今回、私も実際にメジャーアップデートのPRを出したりレビューの数を一気に増やしてみて分かったんですが、破壊的変更を行うPRは簡単にマージされることがほとんどありません。PRやIssue上で長きに渡る議論が発生し、ときにはWGやTSCで議決を取ることにもなります。例えば、今回の破壊的変更であるunhandledRejectionに関する議論は2015年より行われており(link, link)、破壊的変更についてユーザーへのアンケート(link)とブログでの周知(link)も実施されました。

以上のように、議論ではより良い結論を出すために自分の主張を構造化しつつ、ファクトを交えながら建設的に意見を展開する努力が散見されます。そして重要なのが、全ての意思判断プロセスはオープンであり、誰でも参加できる、ということです。

今回のメジャーアップデートに関して皆さんの中でも何かしら意見が出てくるかとは思いますが、興味が出た方はぜひ https://github.com/nodejs から参加してみてください。

npm v7の主な変更点まとめ

こんにちは@watildeです。趣味でnpmへのコミットをたまにしているのですが、最近はNode.js側に比重を置いているのでv7のキャッチアップに少し遅れてしまいました。キャッチアップついでに自分なりに情報をまとめたので、v7における代表的な新機能と破壊的変更について、GitHubの記事よりも少し詳しめに紹介と解説を行ってみます。なるべく参考リンクを付けているので、詳細が気になった際はリンクから一次情報に飛んで読んでみてください。

また、情報に誤りがあった場合はTwitterにて教えていただけると助かります。

背景

npmチームより、2020/10/13にnpmの新しいメジャーアップデートであるところのv7の公式リリースが発表されました。8月からbeta版のリリースを繰り返していましたが、2ヶ月かけて内部的なリファクタリングとスモークテストを繰り返して今回の発表に至ったのかと思います。また、正式なGAは来週の火曜日に予定されており、それまではクオリティ調整に使うとのことです。

プロダクトチームによるアナウンス

2020/10/20に予定されているNode.jsの次のメジャーアップデートのv15に同梱される予定ですが、手元でも npm i -g npm@7 を実行することでインストールができます。ただ、メジャーアップデートということで破壊的変更がいくつか含まれているので、内容を精査してから試すことをおすすめします。

詳細については、下記のnpmの作者による記事にまとまっています。

開発チームによるアナウンス

代表的な新機能の紹介

Workspaceによるmonorepoのサポート

Yarnと同様に、package.json内でworkspaceの場所を指すファイルをworkspacesプロパティに指定することで、npm installを実行した際にchildパッケージのdepdendyが同時にインストールされます。

// package.jsonのworkspacesとファイル構成
├── package.json { "workspaces": ["packages/*"] }
└──packages
├── dep-a 
│  └── package.json { "dependencies": { "dep-b": "^1.0.0" } }
└── dep-b
└── package.json { "version": "1.3.1" }

// インストールをした後のシンボリックリンクによるファイル構成
$ npm install
├── node_modules
│   ├── dep-a -> ./dep-a
│   └── dep-b -> ./dep-b
└──packages
├── dep-a 
│ └── package.json { "dependencies": { "dep-b": "^1.0.0" } }
└── dep-b
└── package.json { "version": "1.3.1" }

実装例: https://github.com/watilde/npm-workspace-example

workspacesプロパティの形式は簡略版も含めて下記の2種類が、パスはglob形式がサポートされてます。

通常版

{
  "name": "workspace-example",
  "version": "1.0.0",
  "workspaces": {
    "packages": [
      "packages/*"
    ]
  }
}

簡略版

{
  "name": "workspace-example",
  "version": "1.0.0",
  "workspaces": [
    "packages/*"
  ]
}

参考: https://github.com/npm/rfcs/blob/13ff09b49c47b144ed35ada6a15883da31f13cf2/implemented/0026-workspaces.md

npm runのmonorepoサポート

参考: https://github.com/npm/rfcs/blob/latest/implemented/0024-npm-run-traverse-directory-tree.md

yarn.lockのサポート

npm installを実行した際に、yarn.lockファイルが利用可能であればmetaファイルとして活用されます。cacheファイルは下記の順番で優先されて利用されます。

  1. node_modules/.package-lock.json
  2. npm-shrinkwrap.json
  3. package-lock.json
  4. yarn.lock

参考: https://github.com/npm/cli/blob/latest/docs/content/cli-commands/npm-install.md#description

package-lock.json v2

yarn.lockがサポートされたにも関わらず、なぜpackage-lock.jsonが存在するのか。それは、npm視点でいくつかの要件を満たしていないからです。今回はそのいくつかの要件のうち、再現性の担保について解説します。

yarn.lockにはversionが無く、Yarnコマンドのバージョンが異なるとnode_modules以下のdependency treeに差異が生まれることがある。例えば、以下のような依存関係がある場合。

root -> (foo@1, bar@1)
foo -> (baz@1)
bar -> (baz@2)

dependency treeは下記の2つになる可能性があります。

root
+-- foo
+-- bar
| +-- baz@2
+-- baz@1

~~ OR ~~

+-- foo
| +-- baz@1
+-- bar
+-- baz@2

この差異により、コード上でrequire("baz")をした際に、v1とv2のどちらが採用されるか分かりません。package-lock.json v2では、dependency treeの再現性を担保した情報を保存します。

参考: https://blog.npmjs.org/post/621733939456933888/npm-v7-series-why-keep-package-lockjson

peerDependencyの自動インストール

package.json内のpeerDependenciesプロパティで管理されているパッケージがnpm install実行時に自動でインストールされるようになります。

参考: https://github.com/npm/rfcs/blob/latest/implemented/0025-install-peer-deps.md

acceptDependenciesの追加

パッケージ開発では通常、ロジックが一切変わっていなくても、サポートするNode.jsのバージョンを上げるためだけの変更でパッケージのバージョンを更新します。acceptDependenciesは、既に他のdependencyで既にインストールされている場合のみ適用されるパッケージを指定することができます。これにより、より効率的なパッケージの再利用が可能となります。

例として、make-dirというパッケージを使って解説します。make-dirは、v1.xではNode.js v4をサポートし、make-dir@2.xmake-dir@3.xではそれ以上のバージョンのNode.jsをサポートします。

例えば、Node.js v8を使ってアプリケーションを開発していて、package.jsonには下記のような情報が入っているとします。

{
    "name": "my-node4-package",
    "engines": {
        "node": ">=4"
    },
    "dependencies": {
        "make-dir": "^1.3.0"
    },
    "acceptDependencies": {
        "make-dir": "2.x - 3.x"
    }
}

この状態で、npm installを実行すると下記のように解決されます。

example-app@0.1.0 /usr/src/npm/example-app
└─┬ my-node4-package@0.1.0
  └─┬ make-dir@1.3.0
    └── pify@3.0.0

その後、make-dirをコードでも利用することになりnpm i make-dirを実行するとします。v7より前のバージョンだと、下記のように解決されますが、

example-app@0.1.0 /usr/src/npm/example-app
├─┬ make-dir@3.0.0
│ └── semver@6.3.0
└─┬ my-node4-package@0.1.0
  └─┬ make-dir@1.3.0
    └── pify@3.0.0

v7のacceptDependenciesを活用すると以下のようになります。

example-app@0.1.0 /usr/src/npm/example-app
├─┬ make-dir@3.0.0
│ └── semver@6.3.0
└─┬ my-node4-package@0.1.0
  └── make-dir@3.0.0 deduped

この例から、acceptDependenciesのユースケースは限定的であると思っています。

2020/10/15 追記: 背景とユースケースについてリプライ頂いたので紹介

参考: https://github.com/npm/rfcs/blob/latest/implemented/0023-acceptDependencies.md

代表的な破壊的変更の紹介

peerDependencyの挙動変更

新機能でも紹介しましたが、実質これはpeerDependencyのインストールの挙動を破壊的に変更しています。影響範囲は小さいと考えられていますが、ここでは破壊的変更として挙げています。

以前の挙動に戻したい場合は--legacy-peer-depsオプションを付けてnpm installを実行することで可能です。karma使ってる人とかpluginのpeerDependencyがsyntax errorになるはずなので利用することになるかと思います。

参考: https://github.com/npm/rfcs/blob/latest/implemented/0025-install-peer-deps.md

npxが実行前に確認

v5.2.0でリリースされたインストールと実行を同時に行うnpxコマンドですが、独立したpackageとして作られていたものがnpm execをコールする実装に内部的には書き換えられました。インストールされていないpackageを実行する際に、下記のように確認を聞かれる挙動が追加されたのが破壊的変更となります。

$ npx create-react-app
Need to install the following packages:
create-react-app
Ok to proceed? (y)

この確認を飛ばしたい場合は、--yes-yオプション指定することで可能です。

その他、npxでの破壊的変更は以下の通り。

  • npm configで宣言されている値がnpxに渡される
  • --no-installオプションは廃止され、--noオプションとして名前が変更
  • パッケージが存在しない際のShellへのフォールバックが廃止
  • -pオプションは、npxでは--packageの省略版でしたが、npm execでは--parseableの省略版として扱う(npm exec -p foonpx -p fooでは違う意味合いになる)
  • --ignore-existingオプションは廃止され、ローカルにインストールされているbinは常にPATHからアクセス可
  • --npm オプションは廃止され、npxは常に同梱元のnpmを利用
  • --node-argオプションと-nオプションが廃止
  • --always-spawnオプションが廃止
  • --shellオプションは--script-shellオプションに名前が変更(後方互換性を目的に残したので、非推奨とのこと)

参考: https://blog.npmjs.org/post/626173315965468672/npm-v7-series-beta-release-and-semver-major

npm auditの出力形式変更

リファクタリングされ、注意喚起をより効果的に行うように出力内容が変更されました。実際に実行してみると、以下のようになります。

$ npm audit
npm audit report
minimist <0.2.1 || >=1.0.0 <1.2.3
Prototype Pollution - https://npmjs.com/advisories/1179
fix available via npm audit fix --force
Will install minimist@1.2.5, which is outside the stated dependency range
node_modules/minimist
1 low severity vulnerability
To address all issues, run:
npm audit fix --force

また、–jsonオプションを付けた場合の出力内容も変更されたので、npm auditを使ったツール開発をしている場合は実装の変更が必要になります。実際に実行してみると、以下のようになります。

{
  "auditReportVersion": 2,
  "vulnerabilities": {
    "minimist": {
      "name": "minimist",
      "severity": "low",
      "via": [
        {
          "source": 1179,
          "name": "minimist",
          "dependency": "minimist",
          "title": "Prototype Pollution",
          "url": "https://npmjs.com/advisories/1179",
          "severity": "low",
          "range": "<0.2.1 || >=1.0.0 <1.2.3"
        }
      ],
      "effects": [],
      "range": "<0.2.1 || >=1.0.0 <1.2.3",
      "nodes": [
        "node_modules/minimist"
      ],
      "fixAvailable": {
        "name": "minimist",
        "version": "1.2.5",
        "isSemVerMajor": false
      }
    }
  },
  "metadata": {
    "vulnerabilities": {
      "info": 0,
      "low": 1,
      "moderate": 0,
      "high": 0,
      "critical": 0,
      "total": 1
    },
    "dependencies": {
      "prod": 1,
      "dev": 0,
      "optional": 0,
      "peer": 0,
      "peerOptional": 0,
      "total": 1
    }
  }
}

package.exportsがnpmの内部モジュールを参照できないように

技術的にはpackage.jsonexportsプロパティでnpmの内部モジュールを指定してrequireが可能だったが廃止。機能として提供すると内部モジュールの実装の変化をするたびに破壊的変更になってしまう、という理由なのかなと予想しています。 

--ignore-scriptsの挙動変更

npm testnpm startnpm stop, and npm restartなどのnpm-scriptsが実行された場合、–ignore-scriptsを指定していても実行されるようになります。ただ、pre, postのライフサイクルスクリプトは実行されません。

参考: https://github.com/npm/rfcs/blob/latest/implemented/0029-add-ability-to-skip-hooks.md

npm testの表示内容の変更

npm-scripts内でtestコマンドが指定されていない場合、今まではecho 'Error: no test specified'package.jsonに自動挿入されていましたが、これからはmissing script: testと表示されます。

npm buildnpm unbuildの廃止

元よりinternalなコマンドで、不要となったので廃止されました。

ソフトウェアエンジニアとして2年半くらい勤めたマッキンゼーを退職しました

各SNSやメールなどで退職報告をしたところ、周りから反響がそれなりに大きく、同じような質問をいくつか受け取ったので簡単によくある質問への回答と簡単な自己紹介と伴に退職記事として書いてみます。

内容に入る前に、冒頭で伝えたいことが2点あります。

1. 退職した会社に対しては100%ポジティブな印象
楽しかった、の一言に尽きます。ある程度の質・量を伴ったアウトプットを出してきたソフトウェアエンジニアが、自身の活動領域を広げて深めるチャレンジを行うのに機会が多くある環境であると推せます。

2. 内部情報や愚痴などは全く書いていません
内部情報を書かないのは当たり前として、愚痴に関しては問題解決であるべきだと個人的に思っています。愚痴は問題として構造化して報告とし、報告を元に解決策を議論しながら提案・合意・実施すれば解消するもの。在籍中も特に問題なく楽しく問題解決として改善できました。

目次

  1. 自己紹介:何者なのか
  2. 活動紹介:何をしてきたか
  3. よくある質問:辞めた理由
  4. よくある質問:次は何をするのか

自己紹介:何者なのか

東京でソフトウェアエンジニアやデジタルコンサルタントをしている @watilde といいます。McKinsey Digital Labsというデジタルの研究所のような部署で、戦略コンサル・デジタルコンサル・ソフトウェアエンジニア・スクラムマスターとして組織改編・DX戦略提案・POCの開発リードなどを様々な業種で実施する仕事をしてきました。プライベートでは、Node.jsやプログラミング教育の分野で活動しています。

活動紹介:何をしてきたか

仕事面

マッキンゼーに入る前は、ソフトウェアエンジニアとして日本・オランダでアプリケーションレイヤーの中でフルスタックエンジニアをしていました。入社後は、日本外の7ヶ国でエネルギー・農業・鉱業・消費・通信・食品などのインダストリーで主にデジタルを利活用するための戦略提案、POC開発、コーチングなどを行ってきました。戦略というとふわふわっとしたイメージが自分にはありましたが、実際に行ってみると大きなソフトウェアの開発でたまに採用されるNexusに近いものを感じました。例えばプロダクト開発を行う大規模組織を改善する一般的なステップの例として下記のようなものがありますが、組織の特性やフェーズ、目的に応じて0からフレームワークを考えることが多かったように思います。

  1. 未来でプロダクトがユーザーに提供すべき価値は何であるべきか
  2. ゴールを実現するためにはいつどこで誰が何を行うべきか
  3. 最初の一歩を踏み出すのにどのように実現するか実際に共同で実施
  4. 成功した事例を組織内でスケールするためにプロセスの設計とコーチング

ソフトウェアエンジニアとしては、自分でいきなり作りたくなるものでしたが組織が継続的に成長するためには組織としての自己学習を可能とするプロセスが必要となります。また、自己学習も外的要因なしに短期間で獲得することは非常に難しく、詳細度の高い計画作り・実施・効果測定・軌道修正というPDCAを丁寧に回す必要があります。

組織の規模が大きくなればなるほどこの実装の難易度はあがり、狙いがハズレた場合のコストも膨大となります。非専門家の言語で効率よくコミュニケーションが行える専門家による継続的なサポートが結果的にペイしてきた歴史があるのだなと、振り返ると理解できます。

仕事外のOSS等

Node.js分野では、言語そのものへのコミット、npm・Web関連仕様・関連ソフトウェアへのコントリビュート、Linux財団とNode.js関連資格の啓蒙、 @yosuke-furukawa さん・他運営メンバーとNode学園祭やJSConfJPの運営、その他カンファレンスでの登壇などをしてきました。

画像2
AmsterdamJS

プログラミング教育分野ではScratchやhow-to-npmなどプログラミング教育関連OSSへのコントリビュート、NodeSchoolやCoderDojoでメンターをしています。

画像3
HaarlemのNodeschool

よくある質問:辞めた理由

社内外で高い頻度で自分は何がしたいのか考える機会があり、結論としてソフトウェアを通じて自分でダイレクトに社会を改善するときが一番楽しいと感じていることに気付きました。

Node.jsへの貢献は例として分かりやすく、14億以上ダウンロードされているプログラミング言語を少しでも改善することで、1人が書いたコードでも高効率にインパクトを創出することができます。組織改善を通じても当然大規模なインパクトは創出できますが、やはり自分がダイレクトに行えることが自身の幸福度に必要不可欠な要素であることが分かりました。

また、部署には世界レベルの優秀なメンバーが次々に入ってきていたので自分が抜けても問題なく成長していくことは疑う余地はありませんでした。これで、内的要因・外的要因として、どちらも次のチャレンジを行うのにブロッカーはないと判断しました。

よくある質問:次は何をするのか

大枠に分けて、3つのことを考えています。

1. Web開発者をサポートし、より本質的な問題解決に集中できる環境の構築

今はこれを会社員として次の仕事でやろうと考えています。オランダに行ったのも同様のモチベーションだったので、やはり自分の原点はここにあるんだろうなと戻ってきました。

具体的にはmBaaSを通じたプロダクト開発への集中をサポートしたいと考えています。こちらはまだ始まっていないので、公開できる状態になったら改めてお伝えします。

また、GitHub上でメンタリングサポートをスポンサーを通じて開始したので、悩みのある方、個人・法人問わずいましたらぜひ。

https://github.com/sponsors/watilde

2. 医療従事者をデジタルによりサポートし、患者へのよりよい医療の提供

父を含め、家系に医療関係者が多く、問題意識が常に頭にありました。サブとして、自分ができる限りでデジタルを通じて問題解決の手助けをして医療従事者・患者の幸福度の向上ができればと考えています。医療情報について勉強しながら、個人的にツールを作って提供しはじめていますが、こちらも身内用のクローズドなプロダクトなのでまたの機会にお話します。

また、この分野に関心のあるエンジニアは、ぜひお声掛けください。JSコミュニティとかと違って、どこにコミュニティが存在しているのか自分でもまだ分かっておらず…。

3. 自分が問題解決に集中できる仕組みづくり

仕事でマネジメントをはじめてから自分の生活を見返すと、お世辞にも効率が良い生活をしているとは言えませんでした。量・質・時間の軸で情報のインプット・アウトプットの改善をするのに、いくつかルール作りを改めてしてみました。

毎日のGitHub活動
インプットの部分です。過去にも何度か行いましたが、再開することにしました。習慣化することで、ソフトウェアエンジニアが何に困っているか自身がペルソナとなって理解でき、自分の目標達成の近道になると考えています。

毎週の運動
新型コロナウイルス下で、運動不足が目立つようになりました。室内をジム化したので、3日に1回程度運動を再開してみました。続けねば。

毎月の記事執筆
アウトプットの部分です。現在のところはMediumで記事を書き始めていますが、自分のブログでも記事を書くようにしていこうと考えています。無理せず、月1程度のペースからスタート。

3ヶ月毎の投資
こちらも過去に行っていましたが再開しました。内部者取引にならないように徹底しつつ、社会の問題と人々の活動の変化に敏感になるべく、開始しました。短期取引というよりは、3ヶ月単位くらいで様子を見ながら取引しても問題ない銘柄やコモデティなどを主に保持していきます。

以上近況でした。みなさんも健康にはお気をつけてー

2018年に買ってよかったもの 11点

オランダから日本に帰国し、環境がいろいろと変わったので細かいものを多く買った。その中で、買ってよかったものをここで紹介し、手が滑って購入してしまったこのブログの費用を少しでもカバーできればと思う。

Amazonで買ったもの

自分は完全に楽天ユーザーなんだけど、急ぎで購入するときはAmazonを使っている。ここでは4点のみ紹介する。

ノートパソコン用スタンド Roost

クライアントのオフィスや、出張など、開発環境が安定しない1年になった。首を悪くしそうだったので、このスタンドと、AppleのMagic Keyboard/Magic Trackpadで乗り切った。非常に良い。

61WAOftz+kL._SL1273_.jpg

名刺入れ m+/

仕事が変わり、名刺交換をする機会が増えてきた。オフィスに立ち寄る機会も少ないので、補充ができるだけ不要なように100枚入る名刺入れを探して購入した。写真のとおり、薄くも分厚くもなるので、薄くなってきたタイミングで補充をしている。

31Zn2OOm1tL.jpg

アイマスク PLEMO

今年は非常に海外出張が多かったので、毎日ちゃんと良質な睡眠が取れるかどうかが重要だった。このアイマスクはつけ心地もよく、遮光性も高い。これに加え、シャッフル睡眠を取り入れてシュッと寝れるようになった。

51MLxfk+SPL._SL1000_.jpg

耳スコープ Teslong

飛行機に乗る回数が増えたからか、耳のトラブルが増えた。海外にいるときは、あまり気軽に病院にいけないので、耳のトラブルに関しては自分でこのスコープを使って観察して、できる限りの対応をしている。

51RpMR5CijL._SL1001_.jpg

楽天で買ったもの

いつでも大体10%オフになるのでAmazonと比較した結果いつも楽天で買うことが多い。楽天からは、7点ほど紹介する。

メモ帳 Traveler’s note パスポートサイズ

目的は2つあって、領収書の管理と、思考の整理。メモ、のような使い方はあまりしておらず、いつでも持ち運べるサイズ、かつリフィルの種類が豊富なものを探した結果トラベラーズノートに行き着いた。

midori06-i00.jpg

フィットネスグローブ ナイキ

出張先での運動不足を避けるのに、ウェイトトレーニングをはじめた。直後、手がボロボロになったので、保護目的で購入。とても良い。

60669652.jpg

電子書籍リーダー kobo forma

本を読む量が増えたので、購入。見開きが表示できる機能がとても便利で、ソファに座ってゆっくり読書するのに使っている。これのためだけにKindleからKoboに移動してもいいんじゃないかってくらい使いやすい。

main_forma.png

「ながら」イヤホン ambie

プログラミングをする際に、ゾーンに入るためのプレイリストがあって音楽は欠かせないんだけど、一方で、仕事でコミュニケーションをする時間も増えた。いつ話しかけられても100%で対応できるように、環境音も聞こえるイヤホンを、ということで購入。

imgrc0072274092.jpg

シューズ・インソール New Balance

クラブに履いていく靴のソールをこれに変えた。だいぶ動きやすくなった。

rcp.jpg

4色ボールペン LAMY 2000

今のメインのペン。3色リーディングとか、わりとメモに色を使うので4色ペンじゃなきゃ駄目、かつ汎用性のある芯の規格がいい。ということで、ちょっと高かったけどこれを買った。間違いなく生産性あがったので推せる。

lamy-l401.jpg

急速充電器 Anker PowerPort+ 5

荷物の整理の際に、物を減らすために購入。macの充電器とスマホの充電器を同時に持ち歩かなくてよくなった。

imgrc0066206744.jpg


以上。買った本の数もけっこーあるので、折を見て紹介したい。

2019年の目標

メモ代わりに、来年にやりたいことを書いていく。

 

毎日やること

  • Code on GitHub
  • Learn on Duolingo

毎週やること

  • 自転車に乗る

毎月やること

  • 新しい人と会う
  • 記事を書く

毎四半期にやること

  • 登壇

年間を通じて達成したいこと

  • 外務員 2級
  • USCMAの勉強開始
  • CNaVT INFO
  • HSK 3級
  • JSConf JPの開催
  • CISAの勉強開始

30ユーロでルクセンブルクに

前回の記事の続き。アムステルダムからルクセンブルクまで安く移動するのに、Ouibusを利用した。結論から言うと、かなり快適。

乗り場

アムステルダム内の乗り場は分かりにくい場所にある。

Screen Shot 2018-01-07 at 17.30.04.png

Amsterdam City Center – Sloterdijk

 

何もない道路に、時間になるとこんな感じにバスが来る。

 

内装

年末年始のラッシュどきに、流れの逆方向に乗ったみたいでバス1台に10人くらいしか乗ってなかった。運転手の人も「好きな席に座ってね」って言うくらいのゆるさ。

 

シートは、日本の新幹線くらいの大きさ。今回は1人あたり2シート使えたので、持て余す広さ。

 

設備

Wi-fiは普通の速さ。ただ、快適すぎたので寝てた。。

他の国にも

どうも、ベルリンやアントワープに行くのにも使えそうなので、今後もっと活用していきたい。

Ouibusでルクセンブルク行きのバスを予約

 

フランスの格安バスとして有名なOuibusを初めて利用して、オランダからルクセンブルクまでのバスを予約してみた。飛行機での往復だと170ユーロ程度かかるところが、今回は58ユーロで済んだ。安い。

車内も暇しなそう

そして、調べたところ電源とwifiが完備されてる模様。

実際に乗ったら写真を何枚か撮ってこようと思う。たのしみ。