久々に見たら"googleapi"も様子が変わってた
1年以上(もしかしたら2年ぐらいかも)間を空けたら、Google APIのNodeクライアントがまるっきり様子が変わってた。前に書いたときは"googleapis": "^23.0.0"ってpackage.jsonに書いてあって、今は"googleapis": "^37.2.0"。23から37ってすごいメジャーの上げ方です。auth周辺からエンドポイントの取得までだけでも、相当様子が変わってる。最新ではTypeScriptにしっかりなってました。前もTypeScriptで書かれてはいたがゴミみたいな型定義だったのです。当時使ってたDrive API v3を例にあげると。
// googleapis/apis/drive/v3.d.ts (23.0.0) declare function Drive(options: any): void; export = Drive; // 本当に2行だけ。
おいおいこれだけかよっていうのが、サーバは変わらず全く同じRest APIを叩くにも関わらず、クライアントは時を経て以下のように変わってます。
// googleapis/build/src/apis/drive/v3.d.ts (37.2.0) // 省略。たくさんimportしてる export declare namespace drive_v3 { // 省略。たくさん型定義している class Drive { about: Resource$About; changes: Resource$Changes; channels: Resource$Channels; comments: Resource$Comments; files: Resource$Files; permissions: Resource$Permissions; replies: Resource$Replies; revisions: Resource$Revisions; teamdrives: Resource$Teamdrives; constructor(options: GlobalOptions, google?: GoogleConfigurable); } // 省略。たくさん型定義している } // 結局、このファイルは2874行もあった。
ということで、23.0.0ではわずか2行だった型定義が37.2.0では2874行と、物量からして違う。型定義が充実しただけでなく、そもそもに呼び方も変わってるので、また一通りドキュメント読まないとなあ。認証認可関連も当然違うので、JWTで入って指定ユーザーになりすます手順なんてのから調べないといけない。で、サンプルもわかりにくくて結局ソースを追った。
import { google } from 'googleapis'; export async function authorizeDrive( email: string, // サービスアカウントのEメール key: string, // 秘密鍵 subject: string, // なりすましたいアカウントのEメール ): Promise<any> { return Promise.resolve(await google.auth.getClient({ clientOptions: { email, key, subject }, scopes: ['https://www.googleapis.com/auth/drive'], })); }
もうちょい、裏取ってみないと。この先も含めてまだ怪しい。
denoが着々と開発されている
node作者であるRyan Dahl氏がアーキテクチャ設計におけるリベンジとして、nodeと同じくV8をスクリプトエンジンに採用して作ってるTypeScriptのネイティブ実行環境「deno」は、着々と開発されていて今や簡単にインストールできて、すぐ使えます。
curl -fL https://deno.land/x/install/install.sh | sh
ちょっと前までインストーラはPythonだったのにそれも変わってた。Windows環境向けにはPowerShellで用意されています。
nodeとの互換性を全否定してnpmを取り込まなかったので、エコシステムを発生からやり直しのため道のりは遠いと思いますが、すでにポツポツdenoを用いたライブラリやフレームワークが出現していました。denolibオーガナイゼーションにtypeormの空リポジトリがあったのが気になる。
denoのAPIリファレンスに見当たらなかったので正規表現はどうするのかなーと前々から思ってたのだけど、本体issueに要望リクエストが一切出てこないので不思議に思ってたら、実はサクっと動いた。
$ deno > (() => { const m = '0123456789'.match(/(23).*(67)/); if (m) { console.log(m); } return 0; })(); [ "234567", "23", "67" ] 0 > exit(); $
バッチリ正規表現が使えました。なるほど正規表現ってV8のレイヤーで実装されているんですね。ECMAScriptの標準化範囲だから、そりゃそうかと。一方でファイルおよびネットワークのIOなどはdenoのレイヤーであって、そこだけリファレンスでは説明していました。
手元でファイル操作したりネット叩いたりするのに、普通ならPythonやRubyとかでやるようなことを、これからはdenoでできるな。
ファイルの冒頭にこれまでshやpythonでやるように #!~/.deno/bin/deno と書いて、chmod +xしてみたけどそれでは「bad interpreter」エラーが出て動かなかった。#!deno でもダメで、#!/Users/masataka_k/.deno/bin/deno と書けば動く。「~」で動かないのはbashに詳しくなくてよくわからないけどホームフォルダの実名を書いちゃうとポータビリティが無くなるから、次のようにenvを通すようにした。
#!/usr/bin/env deno (() => { const m = '0123456789'.match(/(23).*(67)/); if (m) { console.log(m); } return 0; })();
超面白い。じゃあdenoの本質であるsandboxモデルはちゃんと効いてるか試すと...
#!/usr/bin/env deno import { mkdir } from "deno"; (async () => { await mkdir("new_dir"); return 0; })();
以下のように聞かれます。
Deno requests write access to "new_dir". Grant? [yN]
いちいち聞かれないよう、一行目に #!/usr/bin/env deno --allow-write とドキュメント通りに書き込みを許可するフラグをつけるとOK。試してみたらシェルのカレントフォルダでAPIが動くので、上記スクリプトをパス通しておけば、普通にコマンドとして使える。面白い。
まとめとして、deno版のmkdirコマンドは以下の通り。
#!/usr/bin/env deno --allow-write import { mkdir, args } from "deno"; (async () => { if (args.length === 2) { await mkdir(args[1]); } return 0; })();
今後
開発目標に挙げられている、Top Level awaitはまだ実装されていません。
$ deno > await deno.mkdir("new_dir"); SyntaxError: await is only valid in async function >
これができると、コンソールで対話的に実行するのに無名関数で囲って実行するような手間が省ける。
- Aims to be browser compatible.
ブラウザ互換性とは何か?元々のRyan Dhalのプレゼンテーションを解釈するに、ここでは機能として重なる場合にはブラウザでの振る舞いを優先するということなのですけど、詰めれば(プレゼンテーションでは直接そう言ってないけど)将来はdenoで書いたアプリケーションが簡単にブラウザで動くってことなのか?まずGlobalにロードされるブラウザ固有のオブジェクトにTypeScriptでアクセスする方法を用意するのと、今は~/.deno/genに出力しているトランスパイル結果を名前付け直して出力してあげるオプションを作るのかな?
Expressからの...NestJS
続き。何がしたいかというと、REST-fulなAPIをテストしやすく拡張しやすい手法で作りたいだけ。しかしAWSサーバレスの上でTypeScriptにと縛っていくとなかなか答えにたどり着けなかったのです。
NestJS
サーバサイドのフレームワークとしてLoopBack 4の代わりを探していたら検索チェーンの果てで突き当たる。aws-serverless-expressに載せようとしてる中で、おそらくそれら用途で Expressのインスタンスを触れる方法 が用意されていました。さほどExpress感は無いが確かにExpressだったのと、バリバリTypeScript前提な作り。流行りなのかCLIツールも備えてますがまずは無視してフルスクラッチに行きます。LoopBack 4では初期ドキュメントを追っかける限りではCLIを無視できなかったので、これは良い。
// lambda.ts import { createServer, proxy } from 'aws-serverless-express'; import { APIGatewayProxyEvent, Context } from 'aws-lambda'; import { NestFactory } from '@nestjs/core'; import { Server } from 'http'; import * as express from 'express'; import module from './module'; // 追記(後述):実はこの無名クラス取り込みはダメ!!! // 変更例としては「import { UserModule } from './module';」 let server: Server; export default function (event: APIGatewayProxyEvent, context: Context) { if (server) { return proxy(server, event, context); } (async () => { const app = express(); const nest = await NestFactory.create(module, app); await nest.init(); server = createServer(app); proxy(server, event, context); })(); }
NestFactory.createおよびinitが非同期なのでめんどくさい。コールドスタートした時にハンドラが先に動かないようにしないと。一方でホットスタートした時にまた非同期の初期化作業はさせたくなくこんな作り。もっと上手い書き方ありそうなので考え続けてみます。ExpressもLambdaも出てくるのはここまで。これから先はほとんど全てNestJSの上だけで作っていくことが可能。
// /module/user.ts import * as nest from '@nestjs/common'; import * as express from 'express'; @nest.Controller('user') export default class { // 追記(後述):実はこの無名クラスはダメ!!!変更例「export class UserController {」 // 非同期もPromiseを返すだけでOK。簡単に対応できる @nest.Get() async findAll(): Promise<string[]> { return Promise.resolve(['a', 'b', 'c', 'd', 'e']); } @nest.Get('ping') ping(@nest.Response() res: express.Response) { res.send('PING!'); } @nest.Get(':id') findOne(@nest.Param('id') id: string): string { return `This action returns a #${id} user`; } }
デコレータが出てきちゃいました。LoopBack 4でも出てきましたがこいつは10年以上前のJavaのフレームワーク繚乱時代を思い出させます。そこではクラスに付加情報としてJavaではアノテーションと呼ばれていた言語機能を活用してフレームワークやIDEによる介入を行なっていました。上記では@Controllerと@Getで実はルーティングを表現できちゃってる。すなわちfindAllメソッドは、/userで呼び出され、findOneメソッドは、/user/:id で。
pingメソッドでは引数に@Responseデコレータを用いてExpress由来のオブジェクトをDependency Injectionしています。まさにJavaでよくやられた懐かしい手法です。
// /module/index.ts import * as nest from '@nestjs/common'; import user from './user'; @nest.Module({ controllers: [user], }) export default class { // 追記(後述):実はこの無名クラスはダメ!!!変更例、「export class UserModule {」とすべき。 }
NestJS、シンプルにとてもいいんじゃないですかね。LoopBack 4よりは洗練されている気がする。ただ、モジュール間の依存性をDIで解決と言ってるのだけど、特にインターフェイスで疎結合にして実装を分離するのではなく、実クラスをそのままとり回してるのだけどそういうものなのか?Angular由来というDIが昔のSpringやSeasarで馴染んでたDIと狙いというか概念がちょっと違う気がして戸惑っている。まあ、DIの根幹としてコンストラクターを直で呼ばせずにフレームワークがインスタンス生成して、それがちゃんとシングルトンで管理されていれば良いってことかな。
無名クラスを複数個並べた場合の問題
@Module({imports})や@Module({controllers})の値が配列をとるので当然モジュールがグラフ状に広がる作りが可能なはずです。しかし、ここまで私の手元ではそれぞれ一つのモジュールに一つのコントローラーでサンプル程度を作ってる時には動いていましたが、二つ目のモジュールやコントローラを追加すると期待した通りには動かない、DIがきちんと動かないことがありました。
当初、非Lambdaブートストラップ版を書いたり、それをwebpackでビルドして動かしてみたり、公式のサンプルをいくつか持ってきたりして実験していましたが、どうにもうまく動いたり動かなかったり。。。と、しばらくしてトランスパイルされた結果を眺めていて突然閃く。
上記記事で書いた私のコードではモジュールやコントローラを無名クラスで書いてexport defaultしていたのです。これがダメ。NestJSのサンプルもドキュメントも全てそうは書かれてなかったのですが、私のいつもの好む書き癖から無名クラスで書いちゃってました。で、これがNestJSのDIの仕組みの中で一つ目のdefault exportな無名クラスに「default_1」という名前がつけられるのは良いとして、二つ目の無名クラスも同じ名前で被らせてしまうみたいなのです。おそらくここで複数ソースコードに渡って管理されていて「default_2」とでも添字をインクリメントするか、importでつけた名前に書き換えてくれれば問題ないんですけどね。これはトランスパイラーの仕様由来なのかな?現象の再現方法がわかったのでNestJSのコードを追って原因究明とフィードバックをいつかの課題としておきたいと思います。
おそらく私以外にもハマる人いるはず!いないかな?NestJSのインジェクション対象(自分でコンストラクター呼び出しでインスタンスを作らないもの)は無名クラスはダメ。お気をつけください。
supertestとnock
自然な流れで、supertest。結構軽量な作りでhttp.Serverベースのアプリケーションを直接テスト内でアクセスするアサーションライブラリ。
こちらのnockは外部APIをモック化するライブラリ。
常用のjestにてsupertestとnockを組み合わせたら便利じゃないかなと想像している。まだ必要になるところまで届いていないので、想像だけ、備忘録としてだけ。
サーバレスでExpressと再会
eslint-typescript (様子見)
tslintとtslint-config-airbnbを常用していますが、中の人による上記記事ではいずれ世の中はtslintからeslintに移行されていくってことが予見されています。eslintの方が設定をpackage.jsonの中に書けるってのが好き。IDEやビルドツール群との連携は元々eslintの方が強いので、ルールのTypeScript対応が成熟してくれば。現在困ってないので今はちょっと待ちで、近い将来に移行してみようと思う。過渡的にeslintでtslintのルールを使うブリッジが提供されているけど特に狙いもないので冗長なので、eslintネイティブにいい感じになるのを様子見ながら待ち。
serverless-webpack
今まで使ってたserverless-plugin-typescripitでは、コードのコンパイルについてゼロ設定で対応してくれるけど、node_modulesはそのままクラウドへ持ち上げるのでデプロイの際に無駄に大きなパッケージを作ります。Jestとか@types以下全部とか、明らかに不要なものが含まれています。webpackでまとめて小さくするととてもコンパクトになり、結果としてデプロイ速度もスピンアップも早くなりとても有用です。
SPAを作る時にはクソめんどくさいwebpack設定も、この用途ではTypeScriptをコンパイルするだけなのでシンプルです。特にプロジェクト毎に変わるものでは無いので一度作ったらしばらく使い回しできる。
// webpack.config.js const path = require('path'); const serverlessWebpack = require('serverless-webpack'); const webpackNodeExternals = require('webpack-node-externals'); module.exports = { mode: serverlessWebpack.lib.webpack.isLocal ? "development" : "production", entry: serverlessWebpack.lib.entries, resolve: { extensions: [ '.js', '.json', '.ts' ] }, output: { libraryTarget: 'commonjs', path: path.join(__dirname, '.webpack'), filename: '[name].js' }, target: 'node', externals: [webpackNodeExternals()], module: { rules: [ { enforce: 'pre', test: /\.ts$/, use: [ { loader: 'tslint-loader', options: { typeCheck: true, emitErrors: true, }, }, ], }, { test: /\.ts$/, use: [ { loader: 'ts-loader' } ], } ] } };
さらに、serverless.ymlではプラグイン登録と、ちょっと設定が必要。
# serverless.ymlの該当部分 plugins: - serverless-webpack custom: webpack: includeModules: forceExclude: - aws-sdk packager: 'yarn'
webpack設定の方でnode_modulesに入るものを取り除き、serverless設定の方でパッケージに追加しています。custom.webpack.includeModulesはtrueを設定すると依存パッケージを全部取り込みます。aws-sdkは入れなくてもAWS環境側で用意されてますので、forceExcludeにホワイトリスト登録するとパッケージから省く&ワーニングが無いとのこと。
パッケージマネージャーは惰性でyarnを使ってますが、その後の機能追随と速度向上および元々のデフォルト感から、折見てnpmへ戻して良いかもと思っています。
Express
Reactアプリの対となるAPIを作る際に、引き続きAWSのサーバーレス製品群でやろうと思っています。今回の手法としてはServerless Frameworkとaws-serverless-expressでExpressアプリをLambdaへ載せてみてます。
今まではLambda上でExpressを使うことはなんとなく遅くてダメなんじゃないかなと思い込んでたけど、よく考えたらExpressのミドルウェアによってちょっとぐらいコールスタックが増えてもパワフルな現代のコンピューターの前にはなんの影響もないだろうし、一個のLambdaでエンドポイントだけ面倒見てもらってそれ以下はExpressのコードで書いた方が見通しもよく、変更にも強く、テストもしやすく、他クラウドへの移植性もよいんじゃないかなと。さらにはServerless Framworkで管理対象が巨大になってくると、背後のCloudFormationの由来にてリソース上限数制限200個が来るから、Lambdaが一個になってれば当然制限を避けられる。
社内でちょっと話してた時に指摘されたのは、多数Lambaがそれぞれ立ち上がるよりはコールドスタートが掛かりにくいってメリットはあるかもと。そしてLambdaなのにExpressで書いて良いってことになればExpressの既存知識や膨大な世間のコード資産が有効活用できそう。
# serverless.yml service: express provider: name: aws runtime: nodejs8.10 stage: dev region: ap-northeast-1 plugins: - serverless-webpack custom: webpack: includeModules: forceExclude: - aws-sdk packager: 'yarn' functions: app: handler: lambda.default events: - http: method: ANY path: '{proxy+}' cors: true
serverless.ymlの方では、methodが「ANY」で、pathが「{proxy+}」を設定します。これはAWSのドキュメントではプロキシ統合と呼んでいる。これでAPI GatewayではルーティングをせずにExpressの方に全てが回って来ます。
// lambda.ts import { createServer, proxy } from 'aws-serverless-express'; import { eventContext } from 'aws-serverless-express/middleware'; import { APIGatewayProxyEvent, Context } from 'aws-lambda'; import * as express from 'express'; // 普通にExpressのインスタンスを作る const app = express(); // aws-serverless-express/middlewareでAPI Gatewayのイベントを搭載してみる // http.Requestですでにアプリを作るのに十分な情報があるので、実戦だったらいらない機能かなと思います。 app.use(eventContext()); type Event = { apiGateway: { event: any; }; }; const dumpEvent: express.Handler = (req, res) => { res.json((req as unknown as Event).apiGateway.event); }; // ここでは例なのでワイルドカードによる全部受けハンドラ登録をExpressに対して行っている。 // 実戦では、app.get('/dump', dumpEvent); というようにメソッドとパスの組み合わせを具体的に設定する。 app.all('*', dumpEvent); // aws-serverless-expressでLambdaと直結する。 const server = createServer(app); export default function (event: APIGatewayProxyEvent, context: Context) { proxy(server, event, context); }
上記ではとりあえず例としてExpressでもワイルドカード利用でリクエスト全部受けのコード書いてますが、実戦ではExpressのルーティング作法で細かく普通にやればよく、そうすれば想定外パスへのリクエストはExpressの機能として404が返ります。
Serverless Components (様子見)
Serverless Frameworkが定義ファイルからCloudFormationテンプレートを生成してクラウド操作するのではなく、定義ファイルからコンポーネントインスタンスが生成されてそれらがAPIを直接操作する仕組みになっていた。これは良いアイディアで良いアーキテクチャだと思うけど、実装として今はまだ未成熟。Serverless Frameworkの先としてうまく融合 or 進化してほしい。
CLIだけでなく コードでデプロイなどの操作を行う機能 も素敵。そのほかそここことなく、Gulpのようなものを目指してるのかなと思った。
Amplify (お蔵入り)
amplify-cliのfunctionやapi機能がTypeScriptにまだ対応していない。また吐き出すScaffoldの構造がちょっと好きじゃないかな。そもそもにExpressでいいじゃないかと思ったのは、AmplifyでAPIを定義する際にCLIが表示する選択肢の中にExpress利用を見つけたからなので、もうちょいTypeScript対応が進めば個人的な見え方は変わると思います。でも今日ではなかった。
LoopBack (お蔵入り)
5年ぐらい前に、自分的には第1期としてNodeに触れていた時期に、チューンドNodeバイナリを提供していたStrongLoopを見つけました。StrongLoopは当時住んでた近所のSan Mateoに会社が所在していたので、そこで開催されたNodeのMeetupに参加するのにオフィスに入ったこともあります。連想的に彼らが作ってたNode上でRESTful-APIを作るCLI/フレームワークとしてLoopBackを触ったことがありましたが当時APIはGo言語で書くことになったのと、モノとして時期尚早感があったので使うことはありませんでした。ニューストピックとしてその後すぐにStrongLoopがIBMに買収されたことまで追いましたが、しばらく忘れていました。Expressを検討する中で懐かしい名前としてStrongLoopとLoopBackがまた出てきた。
ちょうど新しいバージョン4を出す前夜ぐらいなタイミングで、しかもその4はそれまでのコードベースを捨ててTypeScriptで書き直しているということで、俄然興味がでてきます。
CLIで吐き出すのはTypeScriptオンリーでそれは素敵なのですが、フレームワークの作法としてクラスを書いてデコレータでDIするなど昔のJavaフレームワークかのような。製品WEBでGraphQLとかも語ってたのでこれまでの実績捨ててゼロから作り直した動機はこの辺かと期待しましたが。。。分厚い。。。スタックが深いよ、これは。また4はそれまでと異なりExpressベースではなくなっていました。そしてさすがan IBM Company。IBMクラウドを基本に考えているので、サーバレスにはちょっと背を向けてる風な感じ。各クラウドベンダーの独自なマネージドサービスを多用するサーバレスは現時点での競争負け組であるIBMの戦略には合わないみたい。そして、4が出てくるこのタイミングでわざわざExpressベースとはいえ古い3を使うかというと、なんか気が進まない。よってまたLoopBackはそっと閉じて心の隅にしまう。
Tech-on MeetUp#04「APIでつなぐ・つながるFinTecher」
Tech-on MeetUp#04「APIでつなぐ・つながるFinTecher」というイベントに行ってきた。
KDDIの金融な人たちのホストで、じぶん銀行・au WALLETと連携するカブドットコム証券のセッションに、二本立てのようにゲストStripeで、それぞれFintechの入口のところを事例中心に関係者掛け合いの体で盛りだくさんでした。それぞれのコマが30分程度なので掘り下げ浅めで聴きやすくはありましたが、もっと時間をかけて実装的なことも語られるともっとよかった。 じぶん銀行のAPI(Open API+独自API)はとても興味深いが、法人が気合い入れて取り組まねば利用のためのハードルは超えられなさそうという。。。以下は聴きながら取ってたメモの流し込み。
カブドットコム証券、KDDI
じぶん銀行、KDDI
Stripe、600株式会社
- Stripe:クレジットカード周辺の機能をワンストップ&ペーパーレスでAPIサービス提供する
- Stripeを用いるとクレジットカード情報を直接取り扱わないので、結果としてセキュア
- 600:無人コンビニ、AWSとStripeを利用している
- Fintech/キャッシュレスをビジネスマンとしてどう見るか
- ハードウェアビジネス
- ソフトウェアと違って、デプロイサイクルが長く重い
- 不具合の検出の課題
- 見つけた不具合を更新する際の課題
- オンラインとオフラインの境界が曖昧になってきているように、ハードウェアとソフトウェアも融合
- 自分の専門領域を持ちながら隣接領域にも詳しくなると有利。ハードウェアがその一つだと貴重
- ソフトウェアと違って、デプロイサイクルが長く重い
年末年始
あけましておめでとうございます。
年末年始の10連休でコード書こうかと思ってましたが、Diablo3 for SwitchとNFL game passと積んでた「NEVER LOST AGAIN グーグルマップ誕生 (世界を変えた地図)」を読んで(以上、割合順)過ごしました。残る明日はNFLワイルドカードゲームの現地土曜開催分が未明と午前中にLive放送なのと、17pmまでスプラトゥーン2のフェスなのでほとんど非生産的なまま私の休暇は終わりです。
休み中ちょっとだけReactキャッチアップ。v16.3からContextが変更されてReduxいらないじゃん議論を目にしました。私は新しいContextも含めて以下のように3つ併用した方がキレイだと思います。無理にReduxでなんでもやろうとするとか、Reduxを全く使わないとか、極端にすると余計にテクニックを要して複雑かなと、先入観。
- Redux: SPA背後のドメインモデルを持つ
- Context: 複数ビューを必然的にまたぐルーティングとテーマだけを持つか、使わない
- State: 単一ビューに閉じる画面状態だけを持つ。特にフォーム画面ではフォームの情報を取り扱う。前にライブラリ書いた。
しかーし。ReduxをContextに置き換えてみれば山ほどあるReduxお約束コードがシンプルになるメリットがあるかも。しかしここで考察が足りないのは自分的に未経験なGraphQLのSubscribeが入った場合にどうなるか。Redux続行なら多分イベント直結でストアにDispachさせればいいんじゃないなかと思ってるけど、Diable3やっててそこまで手をつけてない。
今日時点ではRedux続行派な私も、数日後には言うこと変わってるかもしれない。ドメインモデルが直感的に書けてテストしやすいままなら、最低限、依存ライブラリをバッサリ絞れるだけでもステキな予感はある。
2018年の振り返り
2018年は色々あった筈なのですが、全体的に印象に乏しい一年でした。米国駐在からの帰任があったのでそれなりにライフイベント満載な筈なのですが。。。単に自分の感受性の問題だろうか?書き出しながらなんとか思い出す。
1月〜4月
2017 to 2018の年越しは日本にいました。4年の駐在を終えて夏に帰任することが決まったために新春帰国してその後の準備を色々するはずだったのです。プライベートではその時期に長女の高校受験というのもありました。長女は12月初めに帰国させて行徳の実家に預け、その後は公立中学校に3学期だけ通わせました。早生まれの彼女は現地での9年生を終了しておらずそのままだと日本では一学年下がってしまうので、日本の中学校に帰国編入して卒業見込みを得ることが必要だったのです。しかもそれは1月に高校入学願書を出す時点で編入していないといけない。帰国子女枠での受験は海外に3年以上住み&帰国から一年以内に進学というのがよくある条件なので、有識者に聞くと夏休みに入ってすぐに母親と子供だけ先に帰って受験準備をするのがベストプラクティスだったようですが、その分せっかくの海外生活経験も短くなります。ウチは頑張ればどうにでもなるだろうとギリギリまで引っ張りました。
私は3ヶ月間都内ホテル住まいで、サイオステクノロジー社内で進めてたサービス開発に支援で関わってサーバーレス on AWSに触れていた他、その先の仕込みでコツコツ古いものを温めたり、新しいことの種まきしたりと。幸いに長女の受験は全勝してくれたので3月中旬には心安らかに米国へ。しかし諸般の事情でこの時点まで帰任先が明確にはなってなかったのです。なんとなく持株会社ではなく事業会社の方に行くことにはなりそうな雰囲気でしたが、それがサイオステクノロジーなのか(そうならばどの事業部なのか)グルージェントなのか、その他のグループ会社なのか決まってなかった。そんな中で暫定的にサービス開発に関わってましたが、結局はそのサービスが管掌される所の技術部門を担当することになりました。そのサービスとはSIOS Coatiで、技術部門はサイオステクノロジー株式会社第一事業部です。確か内示時期はこの長期出張から戻る直前だったような記憶です。
- この時期に取り組んだコト
- AWSのマネージドサービス群。CognitoとStepFunctionsが初物で、Lambda中心にDynamoDB、S3、API Gateway、SQS、CloudWatchなど。
- Serverless Framework。これをキッカケにAWS Cloud Formationを調べたり戻ったり。とても便利でもっと栄えると良いと思う。
- Vue.js。それまでReactに馴染んでた私でしたが、現場がVue.jsでやりたい声に溢れてたので何でもよかろうと採用。。。が、個人的には失敗だった。Reactの方が良かったと12月の今は心の底から思う。FLUX的なストア構造、ルーティング、コンポーネント毎での描画ユニットテスト、それぞれVue.jsでも論点あるのだと思うけど、Reactの方が一周以上先を走ってる。Vue.jsにはエンジン/フレームワークをTypeScriptで全部書き直すことも構想されているらしい次世代に期待。Anglarは結局食わず嫌いだった。
- Hugo。Static Site Generatorを一通り評価しつつ、結果としてバイナリを一つ置くだけのシンプルな環境で、コンテンツもGo Templateでサクサク書けたHugoを選ぶ。多分私がGoは書くけどRubyは書かないってことが大きく影響していると思う。これも良いと思う。栄よ!
- Stripe。必要になってから他の選択は考えもせずに一択。これまでもこれからもAPIが重要。
5月〜6月
サーバレス on AWSでの経験についてAWS Sumitで登壇することになり、プライベートでは不動産巡りも兼ねてまた日本出張二週間。私と長女の通勤通学の便利から目黒線沿線&大型犬飼育可能の条件で、幸いに奥沢に物件見つけて契約。出張から帰るともう米国は残り1ヶ月しかなく、その辺りは引越しの手配とフェアウェルパーティしか覚えてません。
- この時期に取り組んだコト
7月〜8月
6月末に荷物を出してから船便が届くのに2ヶ月かかった。よって家具もなく床で寝てたしTVも無いし。かろうじて食卓だけは米国に持って行かずに実家に預けてたので、家族全員でほとんどの生活がダイニング。猛暑が続き、毎日家でビール飲んでました。ヤッホー・ブルーイング「インドの青鬼」専門、大好き。
仕事としては、「オマエは技術部門の統括だ、以上!」としかJob Descriptionがない中で、社内観察を行いつつApplication Lifecycle Management(もしくはDevOps環境とでもいうべきか)の統合と刷新を始めています。
- この時期に取り組んだコト
- Chatツールの全般評価。Slack、ChatWorks、Yammer、Workplace by FB、Line、Typetalkなど。結果として初めからそうかなと思ってたけどSlackを採用。その後にSlack TeamとTeam PlusとEnterpriseGridを検討し、Team Plusを採用。
- GitHub Enterpriseの評価。初めはGitHub Businessを評価してたけど、コイツだと事故るな、とすぐに思ってEnterprise。AWS上で何度かインスタンスを作っては壊し、その他コラボツールやSSOを検討していった。
- SSO、つまりはIdPの全般評価。初めはAuth0で作ろうと思って組んで書いた。社内で面白がって手伝う雰囲気があったら本気でAuth0を使ったアプリケーションを作ってたかもしれない。が、とにかく面倒になってきて古巣にご存知Gluegent Gateがあったからそっちに転向。
9月〜10月
船便が届いてから行ったことはソファーの貼り替え。業者事例ページでは世田谷区を目黒区って間違ってる。結構なお値段するんで色々な素材&色々なカラーの見本を取り寄せては考え、最終的に白の合皮で貼り替え終わるまでたっぷり2ヶ月はかかった。決め手は犬でした。彼が土足で登るから汚れても掃除しやすい合皮で、掃除しやすい合皮だからこそ白にチャレンジできた。最近毎晩、彼が就寝用に占有していますがさほど手間をかけずともキレイに保てています。あとはたくさん本を読んでた気がする。シリーズで続いているものの新刊追ってなかったのをまとめて読んだり。大きな本屋に行って書棚を眺めていると何か見つかる。亡きトム=クランシーのジャック=ライアンものとか、漫画とかも。
仕事面ではALMの展開で社内にSSOされたSlackとGitHub Entepriseの本番環境を作ってIDを段階的に増やしつつ、メインは中期経営計画(3年)とさらなる長期ビジョン(10年)の策定で社内ワークショップをファシリテーションしたり、内容をまとめたり。ITイベントに積極的に参加するようにし始めたのはこの頃で、理由は米国に行くしばらく前からイベントやコミュニティに参加しないようになってたので新しい人脈改めて広がれば良いなとか、業界どうなってるのかリサーチのため。
- この時期に取り組んだコト
- スクラム。現場課題にマイクロパッチを充てがう傍で、理屈としてスクラムのベストプラクティスについて書籍やイベント参加などで温め直し。
- Business Model Canvas。派生のValue Proposition Canvasとともにビジネスモデルの考察と表現に採用するのに温め直し。ワークショップはワールドカフェにBMCやVPCを自己ブレンドしたやり方を試してみましたが、結果よかったんじゃないかなと思ってる。
- Slackアプリ開発。Slackでまずはスラッシュアプリ(Slackのコメント欄に”/"から始めるコマンドを打つと定められたURLにアクセスして結果をコメント書き出しするアプリ)から。Hello Worldでは超簡単で世のブログでもそこまではよく見るのだけど、セキュアなサードパーティとしての振る舞いを、きちんとトークンを取得し補完するなどの手間を実装するのは、ベストプラクティスが何かは知られていない。で、試行錯誤。サーバーレスでトークンはDynamoDBに補完する仕組み組んでみたけど、多分これでいいんじゃないかなと思う。需要があれば内外に解説します。
11月〜12月
生活環境も流石に落ち着き、土日も特にどこか家族で行くこともなく淡々と。平日に外で飲むことも以前に比べると少なくなって自室で過ごすことが多くなってくる。9月に開幕したNFLで長年応援しているChicago Bearsが今年は強く、NFL GamepassというWEB視聴サービスを購入して熱心に観てます。1試合が2時間半ぐらいなんで、週に3試合から5試合ぐらい観てるとすぐ夜も更ける。特にBearsは冬に勝ち続けてしばらくぶりに地区優勝!大晦日のシーズン最終戦までプレイオフのシード権を巡って期待させてくれて目が離せない。しかも正月からプレイオフでドキドキさせてくれる。
仕事は日常の日米開発体制で少々イシューありつつも、中期で取り組むべき内容について。アウトプットが量的に停滞して来てたので空き時間はコード書くようにしてます。で、React。サーバー側はAWSサーバーレスで、使ったことないものを眺めながらグルグルウロウロしてます。
- この時期に取り組んだコト
年末最後に、Switch版のDiablo3を買っちゃった。。。
2018年の総括
温故知新、ってことです。日本に戻ってそれまで断絶してた知識や関係をアップデートしている。
2019年の抱負
今の所日々の雑たることはたくさんあると思うけど、私が新しいことをやる予算の獲得はままならず手足縛られているので多分ヒマ予測。イベントやコミュニティに参加したりコード書いたりしてキャッチアップを進めることと、後半ぐらいには人前に出て自分の考えや知見を喋れたらと思う。社内需要次第ですが、勉強会やハッカソンなども考えます。手元では、もうTypeScriptでReactとAWSのサーバーレスで可能な範囲だけでいいやって感じ。他に色々手を広げる気力がない。気力あればMLaaSとかいよいよの時期なのだろうけど。コンテナでk8sなマイクロサービスとかも、AWS以外のクラウドも、社内に有識者いるのでそちらにオマカセ。
プライベートには、やはりダイエットが重点課題になるでしょう。
新年もどうぞよろしくお願いいたします。