yn2011's blog

技術メモ

GraphQL と Apollo Client / Server を学ぶためにやったこと

GraphQL と Apollo Client / Server を学んだので何をしたかを書いておく。

GraphQL

読んだ本

最初に「初めての GraphQL」で概要を掴んだ。ちなみにこの本は Apollo Client / Server についても書かれている。

併せて、設計パターンや実際の開発で課題となるテーマを把握した。(最初は気づかなかったが、設計ガイドは一部が「初めての GraphQL」 の付録にもなっている)

実装

「初めてのGraphQL」には簡単なWeb アプリを開発するチュートリアルがあるので、それを写経した。多分不完全。

GitHub - pokuwagata/photo-share-api

感想

  • GraphQL + TypeScript はフロントとバックエンドの分業に良さそう。ただし適切なschema の設計と継続的な改善が必要で、経験がないと辛いことも多そう。
  • クエリの書き方をよく忘れる

Apollo Client / Server

GraphQL の実装として、Apollo Client / Server がデファクトらしいので GraphQL を学ぶなら Apollo も必須となる。

読んだ本 / ドキュメント

Apollo については「初めての GraphQL」で概要は掴んだが、実際に手を動かすときに公式のドキュメントを参照することが多かった。

apollo-tooling は個人的に苦手な codegen という schema と クエリから TypeScript の型定義を生成するコマンドと格闘したためよく読んだ。

実装

既存のポートフォリオに無理やり BFF 層を追加して、一部のリクエストを GraphQL に置換してみた。logging も少し試した。

0 → 1 を少しやってみたかったので所謂 todo-mvc を 実装しようとした。単純に全てのリクエストを Apollo Server で処理するだけだとあまり面白くないので、 apollo-client で local state managemet を試してみた。

Client / Server の両方で schema を定義して TypeScript の型定義を生成して... という流れを経験できた。そして apollo-client の local state management は辛いという結論に達して挫折した。

あと Graph Manager というサービスも触ってみた。課金しないと全然試せることが少ないけど、本番運用するなら必須の機能が簡単に使えるっぽい。

感想

graphql-code-generator は TypeScript 使うならほぼ必須。linter は linter としての機能というより error が分かるのが嬉しい。VSCode をちゃんと設定すればエディター上でも分かるようになるんだろうか。

graphql-modules は良さそうだけど、設計がこの ライブラリ にロックインされそうな印象がある。

graphql-config は使っていないが、GraphQL 関連のライブラリとかエディタ毎に設定ファイルを独立して書かなきゃいけない傾向があり、辛いので一括で管理できるようにしてくれるっぽい。確かに設定ファイルどんどん増えてくるのは分かる。

  • schema と 型定義の自動生成により、関数型プログラミングのスタイルで開発できる。

    • 最初に問題を解決するための入力と出力の型を定義して、その型を満たす実装を埋めていくというスタイルの開発が容易に行える(少なくともApollo Server側は)
    • また、型定義を元に VSCode が補完・エラー表示してくれないと Reactと Apollo を使って実装していくのはそもそも現実的なのか?という印象もある
  • React の Component に GraphQL のクエリを紐付けて管理するのはコンポーネント指向感あって良い。ただし複雑な Web アプリケーションだと色々辛い部分もあるんだろうな...

  • 正直 GraphQL の導入は Apollo Server の実装よりもフロント側の方が考えなきゃいけないことが沢山あって大変そうという気持ちになった(まあ今回のサーバー側は REST API の中継しかしてないからかもしれないけど...)

AtCoder Beginner Contest に参加し始めた

AtCoder が毎週開催している AtCoder Beginner Contest (以下ABC)に参加するようになって 1ヶ月程度経ったので何かその辺りのことを書いておく。

今の成績

Rating 132 の灰色 f:id:pokuwagata:20200505212852p:plain

なぜやるか

  • 新しい趣味が欲しかった
  • 実装力の強化
  • 有給消化 + GW で25連休中のため比較的時間がある*1

始める前の実力

コンテストに関係しそうなやつだと

  • 競技プログラミング未経験
  • 高校数学は大体分かる(ただし整数問題は分からない*2)、大学の数学はほぼ忘れた
  • 電子・情報系の学部にいた。ただしコンピュータ・サイエンスはそんなに身に付いていない*3
    • 計算量・ビッグオー記法の概念・数学的な定義は何となく分かる
  • 業務でコード書くエンジニアとしての経験は3年ぐらい
    • C++ は書いたことない
    • 業務はフロントエンドを担当することも多く、複雑なアルゴリズムの実装が要求されたことはない

ABC 初参加前にやったこと

  • AtCoder に限らず、所謂競技プログラミングC++ が主流とのことだったので、まずは C++ の環境構築と学習から始めた(ちなみに、この選択は正しくて、ほぼ全てのAtCoder 関連の記事・解説放送、書籍は C++ を前提にしているので C++ やったことなくても学習した方が絶対効率よく学べる)

環境構築

VSCode の場合について書く。以下が揃えば良い感じに C++ でコンテストに参加できる。

code-runner (C++17 実行) の settings.json

  "code-runner.executorMap": {
    "cpp": "cd $dir && g++ -std=c++1z $fileName && ./a.out",
  },

AOJ ITP1 を解いた

自分の場合は C++ をまったく知らなかったので、レッドコーダーが教える、競プロ・AtCoder上達のガイドライン【初級編:競プロを始めよう】 でオススメされている通りに AOJ の ITP1コースを解いて練習しておくことにした。

愚直に9割ぐらい解いたんですが、注意点としては

  • 解答例は C++14 or 17 を見るようにする (標準ライブラリに慣れる)
  • ある程度プログラミング経験がある場合は全部やらなくていいと思う。 とりあえずA,B 問題に取り組んで解説放送聞いたり提出されたコードを読んだほうが実践的かも
  • ITP1 では標準入力の受け取りに慣れるのが1番大事かも

ABCに初めて参加した

自分はこの時点でA, B 問題までは解けた。コンテスト自体の知識は参加して覚えたほうが早い。(提出方法、問題の形式、誤答するとペナルティが発生する等)

スニペットを用意した

ABC の解説放送のライブコーディングで使われているスニペットを参考にした。自分の場合は start とタイプすると以下が挿入されるように設定している。

  "start-template": {
    "prefix": "start-template",
    "body": [
      "#include <bits/stdc++.h>",
      "#define rep(i,n) for(int i=0; i < (n); i++)",
      "#define lower(s) transform(s.begin(), s.end(), s.begin(), ::tolower)",
      "using namespace std;",
      "using ll = long long;",
      "",
      "int main() {",
      "  $0",
      "  return 0;",
      "}"
    ],
    "description": "basic"
  },

いちいちテンプレートファイルを準備して問題毎にコピーして新しく書き始めるよりも早いと思う。

コンテストで学んだこと

主に数値の取り扱い。Webアプリケーションを書いているだけだと意識することが少ない(気がする)

でもコンテストでは必須の知識だと思う。(A, B 問題でそこを狙ってくるテストケースや問題設定が多いので)

  • int (符号付き32bit 整数) の最大値は 231 -1 で、大体 2.14 * 109 で 、10桁
  • long int (符号付き64bit 整数)の最大値は 263 -1 で、大体 9.22 * 1018 で 、19桁
  • 除算は小数部切り捨て(例 5/2 = 2)
    • 切り上げする場合は (a+b-1) / b説明
  • 最終的な計算結果はオーバーフローしなくても計算途中の評価がオーバーフローすると駄目(例 a * b - ca * b がオーバーフロー)

あと、AtCoder のコンテストで C++ で解答する場合は計算機の性能は大体 108 step / sec ぐらいと想定すると良いみたいです。(例えば O(N) でも 1018 step だと 2sec 以内には絶対に収まらない)

ここに書いてた

今やっていること

週に4時間もコンテスト関連には時間使えていないと思う。土日にコンテストに参加して次のコンテストまでに解説放送聞いて実装してみたりぐらいが限界。

ABC に参加する

忘れない限りは毎週参加している。C, D問題は実戦で学ぶ感じになっている。C問題は慣れれば解けるようになってくる印象。実はそんなに高度なことを要求していないことが多い。

解説放送を聞く

神コンテンツ。これがなければ ABC 止めてたかも。模範解答自体はコンテスト終了と同時に公開されるが、大抵読んでも理解に時間がかかるか何も得られないので、最近は始めから解説放送を聞いている。(これは自分の読解力の問題もある)

D 問題以降は正直ちゃんとアルゴリズム等の実装経験積まないと対応できないことが明らかなんだけど、それをする時間をまとめて取れなさそうなので 解説放送に出てきたものから順に学んでいこうかと思っている。まあいつかは D で要求される範囲全部カバーできるようになるんじゃないかな...

今後の目標

  • コンテストに参加し続ける(後5回ぐらい参加で茶色になりそう)
  • C, D 問題の正答率を上げる
  • 楽しむ

*1:とはいえ次の業務で使う技術や知識のキャッチアップの方が優先なので、余暇を全て費やすことはできないが

*2:整数問題の対策が必要なのは当時は東大ぐらいだったのでやってない。今もそうかもだが

*3:C 言語でダイクストラとかバブルソートとか実装する演習があった記憶はある。当時は理解していた。今は実装は無理

VSCode で Go を書くための環境構築

環境

ゴール

  • 高速な補完、フォーマット、シンタックスハイライトが VSCode で動作する
  • vim-go の :GoImport のようにモジュールを選択して import できる
  • VSCodeデバッグできる(標準入力を伴う場合は入力した上でデバッグしたい)

手順

  • VSCodemicrosoft/vscode-goをインストールする
  • (gopls がローカルにインストールされていない場合は)コマンドパレットから Go: Install/Update tools で gopls を選択
  • settings.jsongo.useLanguageServe を true に設定する
  • フォーマットはデフォルトが goreturns だが、変更する場合は settings.jsongo.formatTool に値を設定する

これで標準入力を伴うデバッグ以外のゴールは達成。めちゃくちゃ簡単だ...

標準入力を伴うデバッグ

これはデバッグに使用する delve が標準入力に対応していないので vscode-go でも対応できないとのことだが、ワークアラウンドが共有されていた。(Cannot debug programs which read from STDIN

追加する内容はこのコメント参照

  • tasks.jsondelve を起動するタスクを追加する
  • launch.json に設定を追加し、起動済みの delve に attachしてデバッグができるようにする

以上を行うと、デバッグ前に1度タスクを実行するという手間は必要ではあるものの、デバッグ開始後に標準入力を受け付けるようになる。

その他

こんなハマり方をする人はいないかもしれないが、注意しましょう。

ちなみにログがないと言っていましたが、ちゃんと出力されていました。( mac なら Library/Application\ Support/Code/logs/ 配下)

あと、自分は Go なら Vim で書けばいいと思っていた派なんですが、フロントエンドは VSCode が圧倒的に向いているし、並行してバックエンドを書きたい場合もあるので VSCode でいいかなという気持ちになりました。

日々の健康状態を記録する CLI ツールを Go で書いた

github.com

多分 go get すれば動くと思う

DEMO

f:id:pokuwagata:20200421022609g:plain

目的

  • 「世界一のプロゲーマーがやっている 努力2.0」を読んだ感想 に書いた「自分が無理をしていないか、常にモニターする」をやりたいな、と思った
  • ノートに書くよりは データの方が集計とか楽だし、CLI なら毎日入力するために他の何かのツールと繋ぎ合わせやすいかなあ(例えば Alfred とか...)と思ったので作った
  • それと次の職場で Go が使われているので、復習がてら素振りをしておきたい

機能

  • 質問をする。答えを csv ファイルに書き込む。
  • 日付指定して質問に答えることもできる。入力を忘れても次の日に挽回可能
  • 質問は json ファイルで任意に定義できる。答えのデータ型と範囲(最小と最大)も定義できるのでバリデーションチェック可能(ここは少し頑張った)

感想

  • Go の暗黙のルール忘れがち
    • 1ディレクトリに1パッケージとか、ディレクトリ名とパッケージ名は実は違っていてもいいとか、ファイル分割したら go run *.go で実行しないといけないとか...
  • manifoldco/promptui は良い感じに入力のインターフェイスを作れて良い
  • Go で csvjson の取り回しは初めてだったが、Go らしい素朴な感じでやれるなと思った
  • 正直 Go でちゃんとした CLI ツールを作るのも初めてで時間かかった気がする
    • オプションと引数の受け取り、ファイルやディレクトリの判定・作成、エラー処理等は1度コード書いておかないと辛そう
  • あと最近 AtCoderC++ で頑張っているので
    • 入力のサイズや範囲に敏感になっている気がする
      • Go は int32, int64 のように明示的に型でビット数を指定可能なのかとか
      • 巨大な csv ファイルを開いたらメモリが不味いんじゃないかとか(軽く調べ感じだと Go がよしなにやってくれる+ユースケースとして想定外なので結局特に手は打っていないが...)
    • C / C++ のように素朴に構造化プログラミングするのが馴染んできている気がする

Rictyのバッククォート`が隣接する文字と重なる問題を解決したメモ

環境

問題

  • スクリーンショットを撮るのを忘れていたが、`が隣の文字と重なってしまっていた(`uがúみたいな感じになる)
  • markdownや文字列リテラルでバッククォートはよく使うんだけど、その度にこれが起きていて微妙な気持ちになっていた

解決策

  • Rictyのバッククオートを修正する
  • 多分簡単には直らないんじゃないかなと思っていたが、重い腰を上げてググってみたらすぐに解決方法が見つかった上にすぐ直った

FontForgeのインストール

  • GUI版もあるが、CLI版で十分なのでbrew install fontforgeする

スクリプト実行

  • 上の記事のコメント欄のスクリプトを保存
  • ./script.sh ~/Library/Fonts/RictyDiminished-Regular.ttf (ファイル名は修正したいフォントに合わせる)
  • ちなみに、VSCodeのフォントで使っている場合は、1度workspaceを開き直さないと表示が変になった

やっぱり気になったことはスルーしないで解決していく姿勢が大事ですね...(案外すぐ直ることも多い)

「勝ち続ける意志力 世界一プロ・ゲーマーの「仕事術」」を読んだ感想

前回の記事に続き、プロゲーマー本シリーズ。今回は勝ち続ける意志力 世界一プロ・ゲーマーの「仕事術」を読んだので感想を書く。最近、自分語りの投稿が増えているのはリモートワークが続いていることと何か関係あるのかもしれない。

成長が目的

  • ときど氏が「ゲームを通じた交流」をモチベーションにしていたのに対して、梅原氏は「自身の成長と人生の充実」こそが目的であるとしているのが対照的
    • ゲーム自体は手段に過ぎない
    • 成長を楽しむという目的で割り切って何かをするのも確かに楽しそう。例えば競技プログラミングは、言語はC++*1だし、複雑なアルゴリズムや数学的な考察は実生活では特に役に立たないので*2モチベーション湧きにくいけど、人生を充実させるための趣味と捉えれば別にいいのかもしれない。(むしろゲームよりは遥かに収入に結びつきやすい競技ではある)

お金が目的の人にとっては、効率の悪い努力とか、荒波に揉まれる経験は必要ないのかもしれない。お金さえ手に入れば、自分自身の成長などなくても満足なのだから。

梅原大吾. 勝ち続ける意志力 世界一プロ・ゲーマーの「仕事術」 (小学館101新書) (Japanese Edition) (Kindle の位置No.972-974). 小学館. Kindle 版.

僕はゲームを楽しみたいとか、ゲームで勝ちたいとか、その程度の気持ちではなく、もう少し別の次元で物事を考えている。やはり、ゲームはあくまでもゲームで、本当の目的は自分自身の成長にある。だから、あえて暗くて険しい道を行く。

(Kindle の位置No.1063-1065). 小学館. Kindle 版.

ゲームを通して自分が成長し、ひいては人生を充実させる。いまは、そのために頑張っているんだ、と。

(Kindle の位置No.1646). 小学館. Kindle 版.

何度か書いてきたことだが、いまの僕は日々の成長、継続に喜びを感じている。そうやって毎日、一歩一歩進んでいる。

(Kindle の位置No.1526-1527). 小学館. Kindle 版.

目標と目的の違い

大会で勝つこと自体を目的にするとろくなことはない。少なくとも僕の場合、結果だけを求めて出場した大会で良い成績を残せたことはない

(Kindle の位置No.1634-1635). 小学館. Kindle 版.

大会というのは、日々の練習を楽しんでいる人間、自分の成長を追求している人間が、遊びというか、お披露目の感覚で出るものではないだろうか。大会における勝利は目標のひとつとしてはいいかもしれないが、目的であってはいけない

(Kindle の位置No.1642-1645). 小学館. Kindle 版.

  • 受験、資格試験、転職なんかにも言えそう。それは目標なのか?目的なのか?
    • 受験(入学)や転職(入社)は目的化してはいけないものの典型だろうなという実感がある
    • 自分も大学受験(入学)は完全に目的化していて、大学生活で何をしたい・どう過ごしたい等は全然想像していなかった...
    • 本当は、自分の興味関心を追求する勉強の通過点であるべきなんだろう
      • 当時の自分は勉強が好きというよりも、テストの点数という「結果」と他者との「競争」、それを通じた「成長」が好きだったのかなとも思う*3
        • でもここをもっと掘り下げると、実は梅原氏と同様に自分に対するコンプレックス、疎外感、アイデンティティの確立みたいなものが関わっていたようにも思えて、なかなか深い。それはまさに、格ゲーで対戦相手を"倒す"こと、強さを求めていた以前の梅原氏の行為と本質的には同じことなのかもしれない

勝っても喜ばず、負けても落ち込まない。結果はあくまでも結果で、自分にとってはもっと大事なことがあるから、どちらにせよすぐ忘れる。

(Kindle の位置No.1812-1813). 小学館. Kindle 版.

何かを目標に、ある一定の時期だけ頑張っていると、目標がすべてになってしまう。そして、目標を達成できなかったときに立ち直れなくなってしまう。

(Kindle の位置No.1862-1863). 小学館. Kindle 版.

  • 梅原氏は、自分のモチベーションが低下して何もしたくなくなることに対する恐れみたいなものを持っている印象
  • 自分も勝ち負けに拘らず、求道者といった感じの生き方を志向していきたい(とはいえ、梅原氏は「飽きるほど勝ってみないとこの感覚は分からないかもしれない」とも講演で話している)

基礎を学ぶ

何かを身につけたいと思うのであれば、丁寧に、慎重に、基本を学ぶべきだ。下手なうちから独自の取り組み方をしたり、自由に伸び伸び練習したりすると、最終的に底の浅い仕上がりになってしまう。少なくとも2年、あるいは3年、基礎を学ぶ必要がある。自分の我を通すことなく、セオリックなことを学ぶべきだと考えている。

(Kindle の位置No.1216-1219). 小学館. Kindle 版.

  • ときど氏が「世界一のプロゲーマーがやっている 努力2.0」でも同じことを書いていた。"丁寧に・慎重に"という部分が印象的。
  • 麻雀は2年ぐらいはまったく成果が出ていなかったそうで、さらっと2年とか書くけど成果でないまま2年は相当辛いと思うので凄い。

継続

毎日、60の幸せを手にするため、作業しているとき以外は逆に自信を持って休むことが大切だ。明日の英気を養うことも、継続的な努力の内なのだから。時間を費やすことだけで努力している気になる人が多いが、限界を超えて打ち込んでも成果は上がらない。1日6時間なら6時間、3時間なら3時間と時間を決めて、集中する方がいい。そして後は自信を持って休む

(Kindle の位置No.1845-1849). 小学館. Kindle 版.

  • これも「世界一のプロゲーマーがやっている 努力2.0」と類似の内容で、ON/OFFの重要性はやっぱり普遍的なんだろうな

嫌悪感

だけど正直、みんなから孤立してゲームを追求するというのは、なかなかどうして辛かった。しかし、ゲームが好きという気持ちを裏切ることはできなかった。

(Kindle の位置No.269-271). 小学館. Kindle 版.

中学卒業のとき、高校卒業のとき、進学先や就職先を決めていく同級生を見ながら、ゲームしかない自分への嫌悪感を拭うことができなかった。

(Kindle の位置No.1440-1442). 小学館. Kindle 版.

  • 梅原氏も当然に1人の人間なんだと思わせる一節
  • 自分もプログラミングは好きだと思うが、やはり他者と自分を比較して、嫌悪感とまでは言わないが、孤立感や、本当に自分はこれでいいのか?と自問自答して憂鬱になったりといった経験はある
  • しかし、プロゲーマーになった後の梅原氏は、ゲームしかない自分が世間から認められることで自身を肯定できるようになったとのこと
    • 自分は何か世間から認められているというわけでもないけど、最近は自分の生き方を他者と比べるようなことはあまりしなくなった。結局、人間はその人らしく生きることしかできないし、それが1番幸せなのかなと思っている

*1:選択は自由だが実質C++デファクトらしい

*2:上位層になるとそれを仕事に活かせるかもしれないけど

*3:逆に純粋に興味があったのは英語、数学(代数系)、歴史(幕末~)ぐらいで偏りあるし、好きな分野だけでコンスタントに試験で得点することは難しい